aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/dav/js/settings-admin-caldav.js4
-rw-r--r--apps/dav/l10n/de.js2
-rw-r--r--apps/dav/l10n/de.json2
-rw-r--r--apps/dav/l10n/de_DE.js2
-rw-r--r--apps/dav/l10n/de_DE.json2
-rw-r--r--apps/dav/l10n/es.js10
-rw-r--r--apps/dav/l10n/es.json10
-rw-r--r--apps/dav/l10n/fr.js8
-rw-r--r--apps/dav/l10n/fr.json8
-rw-r--r--apps/dav/l10n/he.js10
-rw-r--r--apps/dav/l10n/he.json10
-rw-r--r--apps/federatedfilesharing/l10n/de.js3
-rw-r--r--apps/federatedfilesharing/l10n/de.json3
-rw-r--r--apps/federatedfilesharing/l10n/de_DE.js3
-rw-r--r--apps/federatedfilesharing/l10n/de_DE.json3
-rw-r--r--apps/federatedfilesharing/l10n/es.js3
-rw-r--r--apps/federatedfilesharing/l10n/es.json3
-rw-r--r--apps/files/css/merged.scss1
-rw-r--r--apps/files/js/app.js2
-rw-r--r--apps/files_sharing/l10n/he.js7
-rw-r--r--apps/files_sharing/l10n/he.json7
-rw-r--r--apps/files_sharing/lib/Controller/ShareAPIController.php11
-rw-r--r--apps/files_sharing/tests/Controller/ShareAPIControllerTest.php193
-rw-r--r--apps/files_trashbin/l10n/de.js1
-rw-r--r--apps/files_trashbin/l10n/de.json1
-rw-r--r--apps/files_trashbin/l10n/de_DE.js2
-rw-r--r--apps/files_trashbin/l10n/de_DE.json2
-rw-r--r--apps/updatenotification/lib/Settings/Admin.php33
-rw-r--r--apps/user_ldap/lib/Connection.php2
-rw-r--r--apps/user_ldap/tests/ConnectionTest.php4
-rw-r--r--config/config.sample.php2
-rw-r--r--core/Controller/WhatsNewController.php126
-rw-r--r--core/css/guest.css5
-rw-r--r--core/css/mobile.scss11
-rw-r--r--core/css/publicshareauth.css3
-rw-r--r--core/css/styles.scss352
-rw-r--r--core/css/whatsnew.scss31
-rw-r--r--core/js/core.json1
-rw-r--r--core/js/merged-template-prepend.json1
-rw-r--r--core/js/public/whatsnew.js134
-rw-r--r--core/js/sharedialogresharerinfoview.js13
-rw-r--r--core/js/sharedialogshareelistview.js19
-rw-r--r--core/js/shareitemmodel.js15
-rw-r--r--core/js/tests/specs/sharedialogviewSpec.js36
-rw-r--r--core/l10n/de.js3
-rw-r--r--core/l10n/de.json3
-rw-r--r--core/l10n/de_DE.js3
-rw-r--r--core/l10n/de_DE.json3
-rw-r--r--core/l10n/el.js1
-rw-r--r--core/l10n/el.json1
-rw-r--r--core/l10n/es.js6
-rw-r--r--core/l10n/es.json6
-rw-r--r--core/l10n/fr.js4
-rw-r--r--core/l10n/fr.json4
-rw-r--r--core/l10n/hr.js229
-rw-r--r--core/l10n/hr.json227
-rw-r--r--core/l10n/it.js3
-rw-r--r--core/l10n/it.json3
-rw-r--r--core/l10n/pt_BR.js5
-rw-r--r--core/l10n/pt_BR.json5
-rw-r--r--core/routes.php2
-rw-r--r--lib/composer/composer/autoload_classmap.php3
-rw-r--r--lib/composer/composer/autoload_static.php3
-rw-r--r--lib/l10n/de.js5
-rw-r--r--lib/l10n/de.json5
-rw-r--r--lib/l10n/de_DE.js5
-rw-r--r--lib/l10n/de_DE.json5
-rw-r--r--lib/private/DB/MySqlTools.php27
-rw-r--r--lib/private/L10N/Factory.php34
-rw-r--r--lib/private/L10N/LanguageIterator.php137
-rw-r--r--lib/private/Preview/Office.php18
-rw-r--r--lib/private/Share20/ProviderFactory.php2
-rw-r--r--lib/private/Share20/Share.php40
-rw-r--r--lib/private/TemplateLayout.php3
-rw-r--r--lib/private/Updater/ChangesCheck.php11
-rw-r--r--lib/public/L10N/IFactory.php16
-rw-r--r--lib/public/L10N/ILanguageIterator.php74
-rw-r--r--lib/public/Share/IShare.php34
-rw-r--r--settings/l10n/el.js1
-rw-r--r--settings/l10n/el.json1
-rw-r--r--settings/l10n/sl.js4
-rw-r--r--settings/l10n/sl.json4
-rw-r--r--tests/lib/L10N/FactoryTest.php30
-rw-r--r--tests/lib/L10N/LanguageIteratorTest.php98
-rw-r--r--tests/lib/Share20/DefaultShareProviderTest.php17
-rw-r--r--tests/lib/Updater/ChangesCheckTest.php39
86 files changed, 1751 insertions, 474 deletions
diff --git a/apps/dav/js/settings-admin-caldav.js b/apps/dav/js/settings-admin-caldav.js
index cf1a2006f69..1a40c208dfe 100644
--- a/apps/dav/js/settings-admin-caldav.js
+++ b/apps/dav/js/settings-admin-caldav.js
@@ -31,8 +31,8 @@ $('#caldavGenerateBirthdayCalendar').change(function() {
var val = $(this)[0].checked;
if (val) {
- $.post(OC.generateUrl(OC.linkTo("dav", "enableBirthdayCalendar")));
+ $.post(OC.generateUrl('/apps/dav/enableBirthdayCalendar'));
} else {
- $.post(OC.generateUrl(OC.linkTo("dav", "disableBirthdayCalendar")));
+ $.post(OC.generateUrl('/apps/dav/disableBirthdayCalendar'));
}
});
diff --git a/apps/dav/l10n/de.js b/apps/dav/l10n/de.js
index b91c5efd3fb..d7af0e5f459 100644
--- a/apps/dav/l10n/de.js
+++ b/apps/dav/l10n/de.js
@@ -64,10 +64,12 @@ OC.L10N.register(
"Technical details" : "Technische Details",
"Remote Address: %s" : "Entfernte Adresse: %s",
"Request ID: %s" : "Anfragekennung: %s",
+ "There was an error updating your attendance status." : "Es ist ein Fehler beim Aktualisieren Deines Teilnehmerstatus aufgetreten.",
"Please contact the organizer directly." : "Bitte den Organisator direkt kontaktieren.",
"Are you accepting the invitation?" : "Die Einladung annehmen?",
"Tentative" : "Vorläufig",
"Save" : "Speichern",
+ "Your attendance was updated successfully." : "Dein Anwesenheits-Status wurde aktualisiert.",
"CalDAV server" : "CalDAV-Server",
"Send invitations to attendees" : "Einladungen an die Teilnehmer versenden",
"Please make sure to properly set up the email settings above." : "Bitte sicherstellen, dass die E-Mail Einstellungen oben korrekt angegeben sind.",
diff --git a/apps/dav/l10n/de.json b/apps/dav/l10n/de.json
index 5b0f50594fe..c4161d1d1da 100644
--- a/apps/dav/l10n/de.json
+++ b/apps/dav/l10n/de.json
@@ -62,10 +62,12 @@
"Technical details" : "Technische Details",
"Remote Address: %s" : "Entfernte Adresse: %s",
"Request ID: %s" : "Anfragekennung: %s",
+ "There was an error updating your attendance status." : "Es ist ein Fehler beim Aktualisieren Deines Teilnehmerstatus aufgetreten.",
"Please contact the organizer directly." : "Bitte den Organisator direkt kontaktieren.",
"Are you accepting the invitation?" : "Die Einladung annehmen?",
"Tentative" : "Vorläufig",
"Save" : "Speichern",
+ "Your attendance was updated successfully." : "Dein Anwesenheits-Status wurde aktualisiert.",
"CalDAV server" : "CalDAV-Server",
"Send invitations to attendees" : "Einladungen an die Teilnehmer versenden",
"Please make sure to properly set up the email settings above." : "Bitte sicherstellen, dass die E-Mail Einstellungen oben korrekt angegeben sind.",
diff --git a/apps/dav/l10n/de_DE.js b/apps/dav/l10n/de_DE.js
index 9afd85b04e8..4edd79558a8 100644
--- a/apps/dav/l10n/de_DE.js
+++ b/apps/dav/l10n/de_DE.js
@@ -64,10 +64,12 @@ OC.L10N.register(
"Technical details" : "Technische Details",
"Remote Address: %s" : "Entfernte Adresse: %s",
"Request ID: %s" : "Anfragekennung: %s",
+ "There was an error updating your attendance status." : "Es ist ein Fehler beim Aktualisieren Ihres Teilnehmerstatus aufgetreten.",
"Please contact the organizer directly." : "Bitte den Organisator direkt kontaktieren.",
"Are you accepting the invitation?" : "Die Einladung annehmen?",
"Tentative" : "Vorläufig",
"Save" : "Speichern",
+ "Your attendance was updated successfully." : "Ihr Teilnehmerstatus wurde aktualisiert.",
"CalDAV server" : "CalDAV-Server",
"Send invitations to attendees" : "Einladungen an die Teilnehmer versenden",
"Please make sure to properly set up the email settings above." : "Stellen Sie sicher, dass die obigen E-Mail-Einstellungen korrekt sind.",
diff --git a/apps/dav/l10n/de_DE.json b/apps/dav/l10n/de_DE.json
index 5ce95e1edb9..72c60c0c6e6 100644
--- a/apps/dav/l10n/de_DE.json
+++ b/apps/dav/l10n/de_DE.json
@@ -62,10 +62,12 @@
"Technical details" : "Technische Details",
"Remote Address: %s" : "Entfernte Adresse: %s",
"Request ID: %s" : "Anfragekennung: %s",
+ "There was an error updating your attendance status." : "Es ist ein Fehler beim Aktualisieren Ihres Teilnehmerstatus aufgetreten.",
"Please contact the organizer directly." : "Bitte den Organisator direkt kontaktieren.",
"Are you accepting the invitation?" : "Die Einladung annehmen?",
"Tentative" : "Vorläufig",
"Save" : "Speichern",
+ "Your attendance was updated successfully." : "Ihr Teilnehmerstatus wurde aktualisiert.",
"CalDAV server" : "CalDAV-Server",
"Send invitations to attendees" : "Einladungen an die Teilnehmer versenden",
"Please make sure to properly set up the email settings above." : "Stellen Sie sicher, dass die obigen E-Mail-Einstellungen korrekt sind.",
diff --git a/apps/dav/l10n/es.js b/apps/dav/l10n/es.js
index 87650f1e109..398741d9626 100644
--- a/apps/dav/l10n/es.js
+++ b/apps/dav/l10n/es.js
@@ -54,12 +54,22 @@ OC.L10N.register(
"Where:" : "Dónde:",
"Description:" : "Descripción:",
"Link:" : "Enlace:",
+ "Accept" : "Aceptar",
+ "Decline" : "Rechazar",
+ "More options ..." : "Más opciones...",
+ "More options at %s" : "Más opciones en %s",
"Contacts" : "Contactos",
"WebDAV" : "WebDAV",
"WebDAV endpoint" : "Extremo del WebDAV",
"Technical details" : "Detalles técnicos",
"Remote Address: %s" : "Dirección remota: %s",
"Request ID: %s" : "ID de solicitud: %s",
+ "There was an error updating your attendance status." : "Ha habido un error al actualizar tu estado de asistencia.",
+ "Please contact the organizer directly." : "Por favor, contacta directamente con el organizador.",
+ "Are you accepting the invitation?" : "¿Aceptas la invitación?",
+ "Tentative" : "Provisional",
+ "Save" : "Guardar",
+ "Your attendance was updated successfully." : "Tu asistencia se ha actualizado con éxito.",
"CalDAV server" : "Servidor CalDAV",
"Send invitations to attendees" : "Enviar invitaciones a los asistentes",
"Please make sure to properly set up the email settings above." : "Por favor, asegúrate de que las configuraciones de correo de arriba son correctas",
diff --git a/apps/dav/l10n/es.json b/apps/dav/l10n/es.json
index b301eeb8e6d..d31347608a3 100644
--- a/apps/dav/l10n/es.json
+++ b/apps/dav/l10n/es.json
@@ -52,12 +52,22 @@
"Where:" : "Dónde:",
"Description:" : "Descripción:",
"Link:" : "Enlace:",
+ "Accept" : "Aceptar",
+ "Decline" : "Rechazar",
+ "More options ..." : "Más opciones...",
+ "More options at %s" : "Más opciones en %s",
"Contacts" : "Contactos",
"WebDAV" : "WebDAV",
"WebDAV endpoint" : "Extremo del WebDAV",
"Technical details" : "Detalles técnicos",
"Remote Address: %s" : "Dirección remota: %s",
"Request ID: %s" : "ID de solicitud: %s",
+ "There was an error updating your attendance status." : "Ha habido un error al actualizar tu estado de asistencia.",
+ "Please contact the organizer directly." : "Por favor, contacta directamente con el organizador.",
+ "Are you accepting the invitation?" : "¿Aceptas la invitación?",
+ "Tentative" : "Provisional",
+ "Save" : "Guardar",
+ "Your attendance was updated successfully." : "Tu asistencia se ha actualizado con éxito.",
"CalDAV server" : "Servidor CalDAV",
"Send invitations to attendees" : "Enviar invitaciones a los asistentes",
"Please make sure to properly set up the email settings above." : "Por favor, asegúrate de que las configuraciones de correo de arriba son correctas",
diff --git a/apps/dav/l10n/fr.js b/apps/dav/l10n/fr.js
index 291e5615265..eb814d7a6cb 100644
--- a/apps/dav/l10n/fr.js
+++ b/apps/dav/l10n/fr.js
@@ -54,11 +54,19 @@ OC.L10N.register(
"Where:" : "Où :",
"Description:" : "Description :",
"Link:" : "Lien :",
+ "Accept" : "Accepter",
+ "Decline" : "Refuser",
+ "More options ..." : "Plus d'options ...",
+ "More options at %s" : "Plus d'options à %s",
"Contacts" : "Contacts",
"WebDAV" : "WebDAV",
"Technical details" : "Détails techniques",
"Remote Address: %s" : "Adresse distante : %s",
"Request ID: %s" : "ID de la requête : %s",
+ "Please contact the organizer directly." : "Merci de contacter l'organisateur directement.",
+ "Are you accepting the invitation?" : "Acceptez-vous l'invitation ?",
+ "Tentative" : "Provisoire",
+ "Save" : "Sauvegarder",
"CalDAV server" : "Serveur CalDAV",
"Send invitations to attendees" : "Envoyer des invitations aux participants",
"Please make sure to properly set up the email settings above." : "Merci de vérifier d'avoir correctement configuré les paramètres de courriel ci-dessus",
diff --git a/apps/dav/l10n/fr.json b/apps/dav/l10n/fr.json
index b09c10b96f3..672e6aec7e3 100644
--- a/apps/dav/l10n/fr.json
+++ b/apps/dav/l10n/fr.json
@@ -52,11 +52,19 @@
"Where:" : "Où :",
"Description:" : "Description :",
"Link:" : "Lien :",
+ "Accept" : "Accepter",
+ "Decline" : "Refuser",
+ "More options ..." : "Plus d'options ...",
+ "More options at %s" : "Plus d'options à %s",
"Contacts" : "Contacts",
"WebDAV" : "WebDAV",
"Technical details" : "Détails techniques",
"Remote Address: %s" : "Adresse distante : %s",
"Request ID: %s" : "ID de la requête : %s",
+ "Please contact the organizer directly." : "Merci de contacter l'organisateur directement.",
+ "Are you accepting the invitation?" : "Acceptez-vous l'invitation ?",
+ "Tentative" : "Provisoire",
+ "Save" : "Sauvegarder",
"CalDAV server" : "Serveur CalDAV",
"Send invitations to attendees" : "Envoyer des invitations aux participants",
"Please make sure to properly set up the email settings above." : "Merci de vérifier d'avoir correctement configuré les paramètres de courriel ci-dessus",
diff --git a/apps/dav/l10n/he.js b/apps/dav/l10n/he.js
index 31acad1c1e5..2f91c82d3e5 100644
--- a/apps/dav/l10n/he.js
+++ b/apps/dav/l10n/he.js
@@ -53,12 +53,22 @@ OC.L10N.register(
"Where:" : "איפה:",
"Description:" : "תיאור:",
"Link:" : "קישור:",
+ "Accept" : "קבלה",
+ "Decline" : "דחייה",
+ "More options ..." : "אפשרויות נוספות…",
+ "More options at %s" : "אפשרויות נוספים ב־%s",
"Contacts" : "אנשי קשר",
"WebDAV" : "WebDAV",
"WebDAV endpoint" : "נקודת קצה WebDAV",
"Technical details" : "פרטים טכניים",
"Remote Address: %s" : "כתובת מרוחקת: %s",
"Request ID: %s" : "מזהה בקשה: %s",
+ "There was an error updating your attendance status." : "אירעה שגיאה בעת עדכון מצב ההשתתפות שלך.",
+ "Please contact the organizer directly." : "נא ליצור קשר עם הגוף מארגן ישירות.",
+ "Are you accepting the invitation?" : "האם להיענות להזמנה?",
+ "Tentative" : "טנטטיבית",
+ "Save" : "שמירה",
+ "Your attendance was updated successfully." : "ההשתתפות שלך עודכנה בהצלחה.",
"CalDAV server" : "שרת CalDAV",
"Send invitations to attendees" : "שליחת הזמנות למשתתפים",
"Please make sure to properly set up the email settings above." : "נא לוודא שהגדרת את הדוא״ל שלהלן כראוי.",
diff --git a/apps/dav/l10n/he.json b/apps/dav/l10n/he.json
index 3b7cfa1d330..5b46ea6e0a0 100644
--- a/apps/dav/l10n/he.json
+++ b/apps/dav/l10n/he.json
@@ -51,12 +51,22 @@
"Where:" : "איפה:",
"Description:" : "תיאור:",
"Link:" : "קישור:",
+ "Accept" : "קבלה",
+ "Decline" : "דחייה",
+ "More options ..." : "אפשרויות נוספות…",
+ "More options at %s" : "אפשרויות נוספים ב־%s",
"Contacts" : "אנשי קשר",
"WebDAV" : "WebDAV",
"WebDAV endpoint" : "נקודת קצה WebDAV",
"Technical details" : "פרטים טכניים",
"Remote Address: %s" : "כתובת מרוחקת: %s",
"Request ID: %s" : "מזהה בקשה: %s",
+ "There was an error updating your attendance status." : "אירעה שגיאה בעת עדכון מצב ההשתתפות שלך.",
+ "Please contact the organizer directly." : "נא ליצור קשר עם הגוף מארגן ישירות.",
+ "Are you accepting the invitation?" : "האם להיענות להזמנה?",
+ "Tentative" : "טנטטיבית",
+ "Save" : "שמירה",
+ "Your attendance was updated successfully." : "ההשתתפות שלך עודכנה בהצלחה.",
"CalDAV server" : "שרת CalDAV",
"Send invitations to attendees" : "שליחת הזמנות למשתתפים",
"Please make sure to properly set up the email settings above." : "נא לוודא שהגדרת את הדוא״ל שלהלן כראוי.",
diff --git a/apps/federatedfilesharing/l10n/de.js b/apps/federatedfilesharing/l10n/de.js
index 1e599f34f91..233e4d87121 100644
--- a/apps/federatedfilesharing/l10n/de.js
+++ b/apps/federatedfilesharing/l10n/de.js
@@ -18,6 +18,7 @@ OC.L10N.register(
"Couldn't establish a federated share, maybe the password was wrong." : "Federated-Share konnte nicht aufgebaut werden, da eventuell das Passwort falsch ist.",
"Federated Share request sent, you will receive an invitation. Check your notifications." : "Anfrage zum Federated-Share war erfolgreich. Du erhälst eine Einladung. Bitte prüfe deine Benachrichtigungen. ",
"Couldn't establish a federated share, it looks like the server to federate with is too old (Nextcloud <= 9)." : "Federated-Share konnte nicht aufgebaut werden, da der Zielserver eine zu alte Version verwendet (Nextcloud <=9).",
+ "It is not allowed to send federated group shares from this server." : "Das Erstellen einer Federated Cloud Freigabe ist von diesem Server aus nicht erlaubt.",
"Sharing %s failed, because this item is already shared with %s" : "Freigabe von %s fehlgeschlagen, da dieses Objekt schon mit %s geteilt wird",
"Not allowed to create a federated share with the same user" : "Das Erstellen einer Federated Cloud Freigabe mit dem gleichen Benutzer ist nicht erlaubt",
"File is already shared with %s" : "Datei wird bereits mit %s geteilt",
@@ -39,6 +40,8 @@ OC.L10N.register(
"Adjust how people can share between servers." : "Definiere wie die Benutzer Inhalte mit anderen Servern teilen können.",
"Allow users on this server to send shares to other servers" : "Benutzern auf diesem Server das Senden von Freigaben an andere Server erlauben",
"Allow users on this server to receive shares from other servers" : "Benutzern auf diesem Server das Empfangen von Freigaben von anderen Servern erlauben",
+ "Allow users on this server to send shares to groups on other servers" : "Ermögliche Nutzern dieses Servers Freigaben an Gruppen auf anderen Servern zu senden",
+ "Allow users on this server to receive group shares from other servers" : "Ermögliche Nutzern dieses Servers Gruppen-Freigaben von anderen Servern zu empfangen",
"Search global and public address book for users" : "Globale Suche und ein öffentliches Adressbuch für Benutzer",
"Allow users to publish their data to a global and public address book" : "Erlaube Benutzern ihre Daten an ein globales und öffentliches Adressbuch zu veröffentlichen",
"Federated Cloud" : "Federated Cloud",
diff --git a/apps/federatedfilesharing/l10n/de.json b/apps/federatedfilesharing/l10n/de.json
index 320af86e7d5..bd3c195ccae 100644
--- a/apps/federatedfilesharing/l10n/de.json
+++ b/apps/federatedfilesharing/l10n/de.json
@@ -16,6 +16,7 @@
"Couldn't establish a federated share, maybe the password was wrong." : "Federated-Share konnte nicht aufgebaut werden, da eventuell das Passwort falsch ist.",
"Federated Share request sent, you will receive an invitation. Check your notifications." : "Anfrage zum Federated-Share war erfolgreich. Du erhälst eine Einladung. Bitte prüfe deine Benachrichtigungen. ",
"Couldn't establish a federated share, it looks like the server to federate with is too old (Nextcloud <= 9)." : "Federated-Share konnte nicht aufgebaut werden, da der Zielserver eine zu alte Version verwendet (Nextcloud <=9).",
+ "It is not allowed to send federated group shares from this server." : "Das Erstellen einer Federated Cloud Freigabe ist von diesem Server aus nicht erlaubt.",
"Sharing %s failed, because this item is already shared with %s" : "Freigabe von %s fehlgeschlagen, da dieses Objekt schon mit %s geteilt wird",
"Not allowed to create a federated share with the same user" : "Das Erstellen einer Federated Cloud Freigabe mit dem gleichen Benutzer ist nicht erlaubt",
"File is already shared with %s" : "Datei wird bereits mit %s geteilt",
@@ -37,6 +38,8 @@
"Adjust how people can share between servers." : "Definiere wie die Benutzer Inhalte mit anderen Servern teilen können.",
"Allow users on this server to send shares to other servers" : "Benutzern auf diesem Server das Senden von Freigaben an andere Server erlauben",
"Allow users on this server to receive shares from other servers" : "Benutzern auf diesem Server das Empfangen von Freigaben von anderen Servern erlauben",
+ "Allow users on this server to send shares to groups on other servers" : "Ermögliche Nutzern dieses Servers Freigaben an Gruppen auf anderen Servern zu senden",
+ "Allow users on this server to receive group shares from other servers" : "Ermögliche Nutzern dieses Servers Gruppen-Freigaben von anderen Servern zu empfangen",
"Search global and public address book for users" : "Globale Suche und ein öffentliches Adressbuch für Benutzer",
"Allow users to publish their data to a global and public address book" : "Erlaube Benutzern ihre Daten an ein globales und öffentliches Adressbuch zu veröffentlichen",
"Federated Cloud" : "Federated Cloud",
diff --git a/apps/federatedfilesharing/l10n/de_DE.js b/apps/federatedfilesharing/l10n/de_DE.js
index 34ddad87d82..10ca881f244 100644
--- a/apps/federatedfilesharing/l10n/de_DE.js
+++ b/apps/federatedfilesharing/l10n/de_DE.js
@@ -18,6 +18,7 @@ OC.L10N.register(
"Couldn't establish a federated share, maybe the password was wrong." : "Federated-Share konnte nicht aufgebaut werden, da eventuell das Passwort falsch ist.",
"Federated Share request sent, you will receive an invitation. Check your notifications." : "Anfrage zum Federated-Share war erfolgreich. Sie erhalten eine Einladung. Bitte prüfen Sie Ihre Benachrichtigungen. ",
"Couldn't establish a federated share, it looks like the server to federate with is too old (Nextcloud <= 9)." : "Federated-Share konnte nicht aufgebaut werden, da der Zielserver eine zu alte Version verwendet (Nextcloud <=9).",
+ "It is not allowed to send federated group shares from this server." : "Das Erstellen einer Federated Cloud Freigabe ist von diesem Server aus nicht zugelassen.",
"Sharing %s failed, because this item is already shared with %s" : "Die Freigabe von %s ist fehlgeschlagen, da dieses Objekt schon mit %s geteilt wird",
"Not allowed to create a federated share with the same user" : "Das Erstellen einer Federated Cloud Freigabe mit dem gleichen Benutzer ist nicht erlaubt",
"File is already shared with %s" : "Datei wird bereits geteilt mit %s",
@@ -39,6 +40,8 @@ OC.L10N.register(
"Adjust how people can share between servers." : "Definiere wie die Benutzer Inhalte mit anderen Servern teilen können.",
"Allow users on this server to send shares to other servers" : "Benutzern auf diesem Server das Senden von Freigaben an andere Server erlauben",
"Allow users on this server to receive shares from other servers" : "Benutzern auf diesem Server das Empfangen von Freigaben von anderen Servern erlauben",
+ "Allow users on this server to send shares to groups on other servers" : "Ermöglichen Sie Nutzern dieses Servers Freigaben an Gruppen auf anderen Servern zu senden",
+ "Allow users on this server to receive group shares from other servers" : "Ermöglichen Sie Nutzern dieses Servers Gruppen-Freigaben von anderen Servern zu empfangen",
"Search global and public address book for users" : "Durchsuche globales und öffentliches Adressbuch nach Nutzern",
"Allow users to publish their data to a global and public address book" : "Erlaube Benutzern ihre Daten an ein globales und öffentliches Adressbuch zu veröffentlichen",
"Federated Cloud" : "Federated Cloud",
diff --git a/apps/federatedfilesharing/l10n/de_DE.json b/apps/federatedfilesharing/l10n/de_DE.json
index 8143801d533..b1df9f5a4ee 100644
--- a/apps/federatedfilesharing/l10n/de_DE.json
+++ b/apps/federatedfilesharing/l10n/de_DE.json
@@ -16,6 +16,7 @@
"Couldn't establish a federated share, maybe the password was wrong." : "Federated-Share konnte nicht aufgebaut werden, da eventuell das Passwort falsch ist.",
"Federated Share request sent, you will receive an invitation. Check your notifications." : "Anfrage zum Federated-Share war erfolgreich. Sie erhalten eine Einladung. Bitte prüfen Sie Ihre Benachrichtigungen. ",
"Couldn't establish a federated share, it looks like the server to federate with is too old (Nextcloud <= 9)." : "Federated-Share konnte nicht aufgebaut werden, da der Zielserver eine zu alte Version verwendet (Nextcloud <=9).",
+ "It is not allowed to send federated group shares from this server." : "Das Erstellen einer Federated Cloud Freigabe ist von diesem Server aus nicht zugelassen.",
"Sharing %s failed, because this item is already shared with %s" : "Die Freigabe von %s ist fehlgeschlagen, da dieses Objekt schon mit %s geteilt wird",
"Not allowed to create a federated share with the same user" : "Das Erstellen einer Federated Cloud Freigabe mit dem gleichen Benutzer ist nicht erlaubt",
"File is already shared with %s" : "Datei wird bereits geteilt mit %s",
@@ -37,6 +38,8 @@
"Adjust how people can share between servers." : "Definiere wie die Benutzer Inhalte mit anderen Servern teilen können.",
"Allow users on this server to send shares to other servers" : "Benutzern auf diesem Server das Senden von Freigaben an andere Server erlauben",
"Allow users on this server to receive shares from other servers" : "Benutzern auf diesem Server das Empfangen von Freigaben von anderen Servern erlauben",
+ "Allow users on this server to send shares to groups on other servers" : "Ermöglichen Sie Nutzern dieses Servers Freigaben an Gruppen auf anderen Servern zu senden",
+ "Allow users on this server to receive group shares from other servers" : "Ermöglichen Sie Nutzern dieses Servers Gruppen-Freigaben von anderen Servern zu empfangen",
"Search global and public address book for users" : "Durchsuche globales und öffentliches Adressbuch nach Nutzern",
"Allow users to publish their data to a global and public address book" : "Erlaube Benutzern ihre Daten an ein globales und öffentliches Adressbuch zu veröffentlichen",
"Federated Cloud" : "Federated Cloud",
diff --git a/apps/federatedfilesharing/l10n/es.js b/apps/federatedfilesharing/l10n/es.js
index caeacddf18b..a16803e9e3f 100644
--- a/apps/federatedfilesharing/l10n/es.js
+++ b/apps/federatedfilesharing/l10n/es.js
@@ -18,6 +18,7 @@ OC.L10N.register(
"Couldn't establish a federated share, maybe the password was wrong." : "No se pudo establecer un compartido remoto, puede que la contraseña fuera incorrecta.",
"Federated Share request sent, you will receive an invitation. Check your notifications." : "Petición de recurso compartido federado enviada, recibirás una invitación. Comprueba tus notificaciones.",
"Couldn't establish a federated share, it looks like the server to federate with is too old (Nextcloud <= 9)." : "No se ha podido establecer un compartido federado, parece ser que el servidor a federar es demasiado antiguo (Nextcloud <= 9).",
+ "It is not allowed to send federated group shares from this server." : "No está permitido enviar compartidos de grupos federados desde este servidor.",
"Sharing %s failed, because this item is already shared with %s" : "Fallo al compartir %s, ya que este elemento ya está compartido con %s",
"Not allowed to create a federated share with the same user" : "No se permite crear un recurso compartido federado con el mismo usuario",
"File is already shared with %s" : "El archivo ya está siendo compartido con %s",
@@ -39,6 +40,8 @@ OC.L10N.register(
"Adjust how people can share between servers." : "Ajusta cómo la gente puede compartir entre servidores.",
"Allow users on this server to send shares to other servers" : "Permitir a usuarios de este servidor compartir con usuarios de otros servidores",
"Allow users on this server to receive shares from other servers" : "Permitir a usuarios de este servidor recibir archivos de usuarios de otros servidores",
+ "Allow users on this server to send shares to groups on other servers" : "Permite a los usuarios de este servidor enviar recursos compartidos a grupos en otros servidores",
+ "Allow users on this server to receive group shares from other servers" : "Permite a los usuarios de este servidor recibir compartidos de grupo desde otros servidores",
"Search global and public address book for users" : "Buscar libretas de contactos globales y públicas para usuarios",
"Allow users to publish their data to a global and public address book" : "Permitir a los usuarios publicar su información en la libreta de direcciones global y pública",
"Federated Cloud" : "Nube Federada",
diff --git a/apps/federatedfilesharing/l10n/es.json b/apps/federatedfilesharing/l10n/es.json
index 71551c1f2d0..ce8067107f4 100644
--- a/apps/federatedfilesharing/l10n/es.json
+++ b/apps/federatedfilesharing/l10n/es.json
@@ -16,6 +16,7 @@
"Couldn't establish a federated share, maybe the password was wrong." : "No se pudo establecer un compartido remoto, puede que la contraseña fuera incorrecta.",
"Federated Share request sent, you will receive an invitation. Check your notifications." : "Petición de recurso compartido federado enviada, recibirás una invitación. Comprueba tus notificaciones.",
"Couldn't establish a federated share, it looks like the server to federate with is too old (Nextcloud <= 9)." : "No se ha podido establecer un compartido federado, parece ser que el servidor a federar es demasiado antiguo (Nextcloud <= 9).",
+ "It is not allowed to send federated group shares from this server." : "No está permitido enviar compartidos de grupos federados desde este servidor.",
"Sharing %s failed, because this item is already shared with %s" : "Fallo al compartir %s, ya que este elemento ya está compartido con %s",
"Not allowed to create a federated share with the same user" : "No se permite crear un recurso compartido federado con el mismo usuario",
"File is already shared with %s" : "El archivo ya está siendo compartido con %s",
@@ -37,6 +38,8 @@
"Adjust how people can share between servers." : "Ajusta cómo la gente puede compartir entre servidores.",
"Allow users on this server to send shares to other servers" : "Permitir a usuarios de este servidor compartir con usuarios de otros servidores",
"Allow users on this server to receive shares from other servers" : "Permitir a usuarios de este servidor recibir archivos de usuarios de otros servidores",
+ "Allow users on this server to send shares to groups on other servers" : "Permite a los usuarios de este servidor enviar recursos compartidos a grupos en otros servidores",
+ "Allow users on this server to receive group shares from other servers" : "Permite a los usuarios de este servidor recibir compartidos de grupo desde otros servidores",
"Search global and public address book for users" : "Buscar libretas de contactos globales y públicas para usuarios",
"Allow users to publish their data to a global and public address book" : "Permitir a los usuarios publicar su información en la libreta de direcciones global y pública",
"Federated Cloud" : "Nube Federada",
diff --git a/apps/files/css/merged.scss b/apps/files/css/merged.scss
index d65bac512f1..8a11e55c269 100644
--- a/apps/files/css/merged.scss
+++ b/apps/files/css/merged.scss
@@ -2,3 +2,4 @@
@import 'upload.scss';
@import 'mobile.scss';
@import 'detailsView.scss';
+@import '../../../core/css/whatsnew.scss';
diff --git a/apps/files/js/app.js b/apps/files/js/app.js
index 52c92645b2d..c2cef563fa0 100644
--- a/apps/files/js/app.js
+++ b/apps/files/js/app.js
@@ -133,6 +133,8 @@
});
this._debouncedPersistShowHiddenFilesState = _.debounce(this._persistShowHiddenFilesState, 1200);
+
+ OCP.WhatsNew.query(); // for Nextcloud server
},
/**
diff --git a/apps/files_sharing/l10n/he.js b/apps/files_sharing/l10n/he.js
index 488c20041a4..e4439d69d27 100644
--- a/apps/files_sharing/l10n/he.js
+++ b/apps/files_sharing/l10n/he.js
@@ -34,8 +34,15 @@ OC.L10N.register(
"{actor} removed share for group {group}" : "הוסר השיתוף עם הקבוצה {group} על ידי {actor}",
"You shared {file} with group {group}" : "שיתפת {file} עם הקבוצה {group}",
"You removed group {group} from {file}" : "הסרת את הקבוצה {group} מהקובץ {file}",
+ "Shared as public link" : "שותף כקישור ציבורי",
"Removed public link" : "הסיר/ה קישור ציבורי",
"Public link expired" : "קישור ציבורי פג תוקף",
+ "{actor} shared as public link" : "שותף כקישור ציבורי על ידי {actor}",
+ "{actor} removed public link" : "הקישור הציבורי הוסר על ידי {actor}",
+ "Public link of {actor} expired" : "תוקף הקישור הציבורי של {actor} פג",
+ "You shared {file} as public link" : "שיתפת את {file} כקישור ציבורי",
+ "You removed public link for {file}" : "הסרת קישור ציבורי עבור {file}",
+ "Public link expired for {file}" : "תוקף הקישור הציבורי עבור {file} פג",
"A file or folder was shared from <strong>another server</strong>" : "קובץ או תיקייה שותפו מ- <strong>שרת אחר</strong>",
"A file or folder has been <strong>shared</strong>" : "קובץ או תיקייה <strong>שותפו<strong/>",
"Wrong share ID, share doesn't exist" : "מספר זיהוי שיתוף שגוי, שיתוף אינו קיים",
diff --git a/apps/files_sharing/l10n/he.json b/apps/files_sharing/l10n/he.json
index 6c278207a48..d45c9f0dfc5 100644
--- a/apps/files_sharing/l10n/he.json
+++ b/apps/files_sharing/l10n/he.json
@@ -32,8 +32,15 @@
"{actor} removed share for group {group}" : "הוסר השיתוף עם הקבוצה {group} על ידי {actor}",
"You shared {file} with group {group}" : "שיתפת {file} עם הקבוצה {group}",
"You removed group {group} from {file}" : "הסרת את הקבוצה {group} מהקובץ {file}",
+ "Shared as public link" : "שותף כקישור ציבורי",
"Removed public link" : "הסיר/ה קישור ציבורי",
"Public link expired" : "קישור ציבורי פג תוקף",
+ "{actor} shared as public link" : "שותף כקישור ציבורי על ידי {actor}",
+ "{actor} removed public link" : "הקישור הציבורי הוסר על ידי {actor}",
+ "Public link of {actor} expired" : "תוקף הקישור הציבורי של {actor} פג",
+ "You shared {file} as public link" : "שיתפת את {file} כקישור ציבורי",
+ "You removed public link for {file}" : "הסרת קישור ציבורי עבור {file}",
+ "Public link expired for {file}" : "תוקף הקישור הציבורי עבור {file} פג",
"A file or folder was shared from <strong>another server</strong>" : "קובץ או תיקייה שותפו מ- <strong>שרת אחר</strong>",
"A file or folder has been <strong>shared</strong>" : "קובץ או תיקייה <strong>שותפו<strong/>",
"Wrong share ID, share doesn't exist" : "מספר זיהוי שיתוף שגוי, שיתוף אינו קיים",
diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php
index 59b763ecf81..d30d5a05a22 100644
--- a/apps/files_sharing/lib/Controller/ShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareAPIController.php
@@ -198,7 +198,7 @@ class ShareAPIController extends OCSController {
$result['token'] = $share->getToken();
$result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]);
- } else if ($share->getShareType() === Share::SHARE_TYPE_REMOTE || $share->getShareType() || Share::SHARE_TYPE_REMOTE_GROUP) {
+ } else if ($share->getShareType() === Share::SHARE_TYPE_REMOTE || $share->getShareType() === Share::SHARE_TYPE_REMOTE_GROUP) {
$result['share_with'] = $share->getSharedWith();
$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'CLOUD');
$result['token'] = $share->getToken();
@@ -212,8 +212,13 @@ class ShareAPIController extends OCSController {
// "name (type, owner) [id]", depending on the Circles app version.
$hasCircleId = (substr($share->getSharedWith(), -1) === ']');
- $displayNameLength = ($hasCircleId? strrpos($share->getSharedWith(), ' '): strlen($share->getSharedWith()));
- $result['share_with_displayname'] = substr($share->getSharedWith(), 0, $displayNameLength);
+ $result['share_with_displayname'] = $share->getSharedWithDisplayName();
+ if (empty($result['share_with_displayname'])) {
+ $displayNameLength = ($hasCircleId? strrpos($share->getSharedWith(), ' '): strlen($share->getSharedWith()));
+ $result['share_with_displayname'] = substr($share->getSharedWith(), 0, $displayNameLength);
+ }
+
+ $result['share_with_avatar'] = $share->getSharedWithAvatar();
$shareWithStart = ($hasCircleId? strrpos($share->getSharedWith(), '[') + 1: 0);
$shareWithLength = ($hasCircleId? -1: strpos($share->getSharedWith(), ' '));
diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
index 2c638fe4ed6..5d376f2d4f7 100644
--- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
@@ -2074,6 +2074,131 @@ class ShareAPIControllerTest extends TestCase {
], $share, [], false
];
+ // Circle with id, display name and avatar set by the Circles app
+ $share = \OC::$server->getShareManager()->newShare();
+ $share->setShareType(\OCP\Share::SHARE_TYPE_CIRCLE)
+ ->setSharedBy('initiator')
+ ->setSharedWith('Circle (Public circle, circleOwner) [4815162342]')
+ ->setSharedWithDisplayName('The display name')
+ ->setSharedWithAvatar('path/to/the/avatar')
+ ->setShareOwner('owner')
+ ->setPermissions(\OCP\Constants::PERMISSION_READ)
+ ->setNode($folder)
+ ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
+ ->setTarget('myTarget')
+ ->setId(42);
+
+ $result[] = [
+ [
+ 'id' => 42,
+ 'share_type' => \OCP\Share::SHARE_TYPE_CIRCLE,
+ 'uid_owner' => 'initiator',
+ 'displayname_owner' => 'initiator',
+ 'permissions' => 1,
+ 'stime' => 946684862,
+ 'parent' => null,
+ 'expiration' => null,
+ 'token' => null,
+ 'uid_file_owner' => 'owner',
+ 'displayname_file_owner' => 'owner',
+ 'path' => 'folder',
+ 'item_type' => 'folder',
+ 'storage_id' => 'storageId',
+ 'storage' => 100,
+ 'item_source' => 2,
+ 'file_source' => 2,
+ 'file_parent' => 1,
+ 'file_target' => 'myTarget',
+ 'share_with' => '4815162342',
+ 'share_with_displayname' => 'The display name',
+ 'share_with_avatar' => 'path/to/the/avatar',
+ 'mail_send' => 0,
+ 'mimetype' => 'myFolderMimeType',
+ ], $share, [], false
+ ];
+
+ // Circle with id set by the Circles app
+ $share = \OC::$server->getShareManager()->newShare();
+ $share->setShareType(\OCP\Share::SHARE_TYPE_CIRCLE)
+ ->setSharedBy('initiator')
+ ->setSharedWith('Circle (Public circle, circleOwner) [4815162342]')
+ ->setShareOwner('owner')
+ ->setPermissions(\OCP\Constants::PERMISSION_READ)
+ ->setNode($folder)
+ ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
+ ->setTarget('myTarget')
+ ->setId(42);
+
+ $result[] = [
+ [
+ 'id' => 42,
+ 'share_type' => \OCP\Share::SHARE_TYPE_CIRCLE,
+ 'uid_owner' => 'initiator',
+ 'displayname_owner' => 'initiator',
+ 'permissions' => 1,
+ 'stime' => 946684862,
+ 'parent' => null,
+ 'expiration' => null,
+ 'token' => null,
+ 'uid_file_owner' => 'owner',
+ 'displayname_file_owner' => 'owner',
+ 'path' => 'folder',
+ 'item_type' => 'folder',
+ 'storage_id' => 'storageId',
+ 'storage' => 100,
+ 'item_source' => 2,
+ 'file_source' => 2,
+ 'file_parent' => 1,
+ 'file_target' => 'myTarget',
+ 'share_with' => '4815162342',
+ 'share_with_displayname' => 'Circle (Public circle, circleOwner)',
+ 'share_with_avatar' => '',
+ 'mail_send' => 0,
+ 'mimetype' => 'myFolderMimeType',
+ ], $share, [], false
+ ];
+
+ // Circle with id not set by the Circles app
+ $share = \OC::$server->getShareManager()->newShare();
+ $share->setShareType(\OCP\Share::SHARE_TYPE_CIRCLE)
+ ->setSharedBy('initiator')
+ ->setSharedWith('Circle (Public circle, circleOwner)')
+ ->setShareOwner('owner')
+ ->setPermissions(\OCP\Constants::PERMISSION_READ)
+ ->setNode($folder)
+ ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
+ ->setTarget('myTarget')
+ ->setId(42);
+
+ $result[] = [
+ [
+ 'id' => 42,
+ 'share_type' => \OCP\Share::SHARE_TYPE_CIRCLE,
+ 'uid_owner' => 'initiator',
+ 'displayname_owner' => 'initiator',
+ 'permissions' => 1,
+ 'stime' => 946684862,
+ 'parent' => null,
+ 'expiration' => null,
+ 'token' => null,
+ 'uid_file_owner' => 'owner',
+ 'displayname_file_owner' => 'owner',
+ 'path' => 'folder',
+ 'item_type' => 'folder',
+ 'storage_id' => 'storageId',
+ 'storage' => 100,
+ 'item_source' => 2,
+ 'file_source' => 2,
+ 'file_parent' => 1,
+ 'file_target' => 'myTarget',
+ 'share_with' => 'Circle',
+ 'share_with_displayname' => 'Circle (Public circle, circleOwner)',
+ 'share_with_avatar' => '',
+ 'mail_send' => 0,
+ 'mimetype' => 'myFolderMimeType',
+ ], $share, [], false
+ ];
+
$share = \OC::$server->getShareManager()->newShare();
$share->setShareType(\OCP\Share::SHARE_TYPE_USER)
->setSharedBy('initiator')
@@ -2088,6 +2213,47 @@ class ShareAPIControllerTest extends TestCase {
[], $share, [], true
];
+ $share = \OC::$server->getShareManager()->newShare();
+ $share->setShareType(\OCP\Share::SHARE_TYPE_EMAIL)
+ ->setSharedBy('initiator')
+ ->setSharedWith('user@server.com')
+ ->setShareOwner('owner')
+ ->setPermissions(\OCP\Constants::PERMISSION_READ)
+ ->setNode($folder)
+ ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
+ ->setTarget('myTarget')
+ ->setId(42)
+ ->setPassword('password');
+
+ $result[] = [
+ [
+ 'id' => 42,
+ 'share_type' => \OCP\Share::SHARE_TYPE_EMAIL,
+ 'uid_owner' => 'initiator',
+ 'displayname_owner' => 'initiator',
+ 'permissions' => 1,
+ 'stime' => 946684862,
+ 'parent' => null,
+ 'expiration' => null,
+ 'token' => null,
+ 'uid_file_owner' => 'owner',
+ 'displayname_file_owner' => 'owner',
+ 'path' => 'folder',
+ 'item_type' => 'folder',
+ 'storage_id' => 'storageId',
+ 'storage' => 100,
+ 'item_source' => 2,
+ 'file_source' => 2,
+ 'file_parent' => 1,
+ 'file_target' => 'myTarget',
+ 'share_with' => 'user@server.com',
+ 'share_with_displayname' => 'mail display name',
+ 'mail_send' => 0,
+ 'mimetype' => 'myFolderMimeType',
+ 'password' => 'password'
+ ], $share, [], false
+ ];
+
return $result;
}
@@ -2131,15 +2297,28 @@ class ShareAPIControllerTest extends TestCase {
$this->overwriteService(\OCP\Contacts\IManager::class, $cm);
$cm->method('search')
- ->with('user@server.com', ['CLOUD'])
- ->willReturn([
- [
- 'CLOUD' => [
- 'user@server.com',
+ ->will($this->returnValueMap([
+ ['user@server.com', ['CLOUD'], [],
+ [
+ [
+ 'CLOUD' => [
+ 'user@server.com',
+ ],
+ 'FN' => 'foobar',
+ ],
+ ],
+ ],
+ ['user@server.com', ['EMAIL'], [],
+ [
+ [
+ 'EMAIL' => [
+ 'user@server.com',
+ ],
+ 'FN' => 'mail display name',
+ ],
],
- 'FN' => 'foobar',
],
- ]);
+ ]));
try {
$result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
diff --git a/apps/files_trashbin/l10n/de.js b/apps/files_trashbin/l10n/de.js
index 860f2473f28..35d03dc4001 100644
--- a/apps/files_trashbin/l10n/de.js
+++ b/apps/files_trashbin/l10n/de.js
@@ -12,6 +12,7 @@ OC.L10N.register(
"This directory is unavailable, please check the logs or contact the administrator" : "Dieses Verzeichnis ist nicht verfügbar, bitte überprüfe die Logdateien oder kontaktiere den Administrator",
"restored" : "Wiederhergestellt",
"This application enables users to restore files that were deleted from the system." : "Diese App ermöglicht es Nutzern Dateien die vom System gelöscht wurden wiederherzustellen",
+ "This application enables users to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the users file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent a user from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Diese Anwendung ermöglicht es Benutzern, gelöschte Dateien wieder herzustellen. Im Webinterface wird eine Liste mit allen gelöschten Dateien angezeigt. Es besteht die Möglichkeit die Datein im Dateiverzeichnisse des Benutzers wieder herzustelle, oder diese endgültig zu löschen. Bei der Wiederherstellung einer Datei werden, sofern die Versions Anwendung aktiviert ist, die dazugehörigen Dateiversionen ebenfalls wieder hergestellt. Falls eine geteilte Datei gelöscht wurde, kann diese ebenfals wieder hergestellt werden, jedoch ist diese danach nicht mehr geteilt. Normalerweise verbleiben gelöschte Dateien für 30 Tage im Papierkorb .\nUm zu verhindern, dass einem Benutzer der Speicherplatz ausgeht, nutzt die Anwendung maximal 50% des verfügbaren freien Kontingents für gelöschte Dateien. Sofern die gelöschten Dateien dieses Limit überschreiten, werden zunächst die ältesten Dateien gelöscht, bis das Limit unterschritten wird. Mehr Informationen sind in der Dokumentation verfügbar.",
"No deleted files" : "Keine gelöschten Dateien",
"You will be able to recover deleted files from here" : "Hier können gelöschte Dateien wiederhergestellt werden",
"No entries found in this folder" : "Keine Einträge in diesem Ordner gefunden",
diff --git a/apps/files_trashbin/l10n/de.json b/apps/files_trashbin/l10n/de.json
index dcf5ba64d26..45c4aef139e 100644
--- a/apps/files_trashbin/l10n/de.json
+++ b/apps/files_trashbin/l10n/de.json
@@ -10,6 +10,7 @@
"This directory is unavailable, please check the logs or contact the administrator" : "Dieses Verzeichnis ist nicht verfügbar, bitte überprüfe die Logdateien oder kontaktiere den Administrator",
"restored" : "Wiederhergestellt",
"This application enables users to restore files that were deleted from the system." : "Diese App ermöglicht es Nutzern Dateien die vom System gelöscht wurden wiederherzustellen",
+ "This application enables users to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the users file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent a user from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Diese Anwendung ermöglicht es Benutzern, gelöschte Dateien wieder herzustellen. Im Webinterface wird eine Liste mit allen gelöschten Dateien angezeigt. Es besteht die Möglichkeit die Datein im Dateiverzeichnisse des Benutzers wieder herzustelle, oder diese endgültig zu löschen. Bei der Wiederherstellung einer Datei werden, sofern die Versions Anwendung aktiviert ist, die dazugehörigen Dateiversionen ebenfalls wieder hergestellt. Falls eine geteilte Datei gelöscht wurde, kann diese ebenfals wieder hergestellt werden, jedoch ist diese danach nicht mehr geteilt. Normalerweise verbleiben gelöschte Dateien für 30 Tage im Papierkorb .\nUm zu verhindern, dass einem Benutzer der Speicherplatz ausgeht, nutzt die Anwendung maximal 50% des verfügbaren freien Kontingents für gelöschte Dateien. Sofern die gelöschten Dateien dieses Limit überschreiten, werden zunächst die ältesten Dateien gelöscht, bis das Limit unterschritten wird. Mehr Informationen sind in der Dokumentation verfügbar.",
"No deleted files" : "Keine gelöschten Dateien",
"You will be able to recover deleted files from here" : "Hier können gelöschte Dateien wiederhergestellt werden",
"No entries found in this folder" : "Keine Einträge in diesem Ordner gefunden",
diff --git a/apps/files_trashbin/l10n/de_DE.js b/apps/files_trashbin/l10n/de_DE.js
index 0426ae8fa80..d250943f662 100644
--- a/apps/files_trashbin/l10n/de_DE.js
+++ b/apps/files_trashbin/l10n/de_DE.js
@@ -12,7 +12,7 @@ OC.L10N.register(
"This directory is unavailable, please check the logs or contact the administrator" : "Dieses Verzeichnis ist nicht verfügbar, bitte überprüfen Sie die Log-Dateien oder kontaktieren Sie den Administrator",
"restored" : "Wiederhergestellt",
"This application enables users to restore files that were deleted from the system." : "Diese Anwendung ermöglicht es Benutzern, Dateien die vom System gelöscht wurden wieder herzustellen.",
- "This application enables users to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the users file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent a user from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Diese Anwendung ermöglicht es Benutzern, Dateien die vom System gelöscht wurden wieder herzustellen. Im Webinterface wird eine Liste mit allen gelöschten Dateien angezeigt. Es besteht die Möglichkeit die Datein im Dateiverzeichnisse des Benutzers wieder herzustelle, oder diese dauerhaft zu entfernen. Bei der Wiederherstellung einer Datei, werden die dazugehörigen Dateiversionen ebenfalls wieder hergestellt, sofern die Versions Anwendung aktiviert war. Falls eine geteilte Datei wieder gelöscht wurde, kann diese ebenfalsl wieder hergestellt werden, jedoch ist diese danach nicht mehr geteilt. Normalerweise sind gelöschte Dateien für 30 Tage im Papierkorb .\nUm zu verhindern, dass einem Benutzer der Speicherplatz ausgeht, nutzt die Anwendung Gelöschte Dateien nicht mehr als 50% des derzeit verfügbaren freien Kontingents für gelöschte Dateien. Falls die gelöschten Dateien dieses Limit überschreiten, werden zuerst die ältesten Dateien gelöscht, bis das Limit unterschritten wird. Mehr Informationen sind in der Dokumentation von Gelöschte Dateien verfügbar.",
+ "This application enables users to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the users file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent a user from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Diese Anwendung ermöglicht es Benutzern, gelöschte Dateien wieder herzustellen. Im Webinterface wird eine Liste mit allen gelöschten Dateien angezeigt. Es besteht die Möglichkeit die Datein im Dateiverzeichnisse des Benutzers wieder herzustelle, oder diese endgültig zu löschen. Bei der Wiederherstellung einer Datei werden, sofern die Versions Anwendung aktiviert ist, die dazugehörigen Dateiversionen ebenfalls wieder hergestellt. Falls eine geteilte Datei gelöscht wurde, kann diese ebenfals wieder hergestellt werden, jedoch ist diese danach nicht mehr geteilt. Normalerweise verbleiben gelöschte Dateien für 30 Tage im Papierkorb .\nUm zu verhindern, dass einem Benutzer der Speicherplatz ausgeht, nutzt die Anwendung maximal 50% des verfügbaren freien Kontingents für gelöschte Dateien. Sofern die gelöschten Dateien dieses Limit überschreiten, werden zunächst die ältesten Dateien gelöscht, bis das Limit unterschritten wird. Mehr Informationen sind in der Dokumentation verfügbar.",
"No deleted files" : "Keine gelöschten Dateien",
"You will be able to recover deleted files from here" : "Hier können gelöschte Dateien wiederhergestellt werden",
"No entries found in this folder" : "Keine Einträge in diesem Ordner gefunden",
diff --git a/apps/files_trashbin/l10n/de_DE.json b/apps/files_trashbin/l10n/de_DE.json
index cef5ee83868..f8aecdb3559 100644
--- a/apps/files_trashbin/l10n/de_DE.json
+++ b/apps/files_trashbin/l10n/de_DE.json
@@ -10,7 +10,7 @@
"This directory is unavailable, please check the logs or contact the administrator" : "Dieses Verzeichnis ist nicht verfügbar, bitte überprüfen Sie die Log-Dateien oder kontaktieren Sie den Administrator",
"restored" : "Wiederhergestellt",
"This application enables users to restore files that were deleted from the system." : "Diese Anwendung ermöglicht es Benutzern, Dateien die vom System gelöscht wurden wieder herzustellen.",
- "This application enables users to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the users file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent a user from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Diese Anwendung ermöglicht es Benutzern, Dateien die vom System gelöscht wurden wieder herzustellen. Im Webinterface wird eine Liste mit allen gelöschten Dateien angezeigt. Es besteht die Möglichkeit die Datein im Dateiverzeichnisse des Benutzers wieder herzustelle, oder diese dauerhaft zu entfernen. Bei der Wiederherstellung einer Datei, werden die dazugehörigen Dateiversionen ebenfalls wieder hergestellt, sofern die Versions Anwendung aktiviert war. Falls eine geteilte Datei wieder gelöscht wurde, kann diese ebenfalsl wieder hergestellt werden, jedoch ist diese danach nicht mehr geteilt. Normalerweise sind gelöschte Dateien für 30 Tage im Papierkorb .\nUm zu verhindern, dass einem Benutzer der Speicherplatz ausgeht, nutzt die Anwendung Gelöschte Dateien nicht mehr als 50% des derzeit verfügbaren freien Kontingents für gelöschte Dateien. Falls die gelöschten Dateien dieses Limit überschreiten, werden zuerst die ältesten Dateien gelöscht, bis das Limit unterschritten wird. Mehr Informationen sind in der Dokumentation von Gelöschte Dateien verfügbar.",
+ "This application enables users to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the users file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent a user from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Diese Anwendung ermöglicht es Benutzern, gelöschte Dateien wieder herzustellen. Im Webinterface wird eine Liste mit allen gelöschten Dateien angezeigt. Es besteht die Möglichkeit die Datein im Dateiverzeichnisse des Benutzers wieder herzustelle, oder diese endgültig zu löschen. Bei der Wiederherstellung einer Datei werden, sofern die Versions Anwendung aktiviert ist, die dazugehörigen Dateiversionen ebenfalls wieder hergestellt. Falls eine geteilte Datei gelöscht wurde, kann diese ebenfals wieder hergestellt werden, jedoch ist diese danach nicht mehr geteilt. Normalerweise verbleiben gelöschte Dateien für 30 Tage im Papierkorb .\nUm zu verhindern, dass einem Benutzer der Speicherplatz ausgeht, nutzt die Anwendung maximal 50% des verfügbaren freien Kontingents für gelöschte Dateien. Sofern die gelöschten Dateien dieses Limit überschreiten, werden zunächst die ältesten Dateien gelöscht, bis das Limit unterschritten wird. Mehr Informationen sind in der Dokumentation verfügbar.",
"No deleted files" : "Keine gelöschten Dateien",
"You will be able to recover deleted files from here" : "Hier können gelöschte Dateien wiederhergestellt werden",
"No entries found in this folder" : "Keine Einträge in diesem Ordner gefunden",
diff --git a/apps/updatenotification/lib/Settings/Admin.php b/apps/updatenotification/lib/Settings/Admin.php
index b859ca79f62..cae62ee0a9f 100644
--- a/apps/updatenotification/lib/Settings/Admin.php
+++ b/apps/updatenotification/lib/Settings/Admin.php
@@ -123,39 +123,18 @@ class Admin implements ISettings {
return $filtered;
}
- $isFirstCall = true;
+ $iterator = $this->l10nFactory->getLanguageIterator();
do {
- $lang = $this->l10nFactory->iterateLanguage($isFirstCall);
- if($this->findWhatsNewTranslation($lang, $filtered, $changes['whatsNew'])) {
- return $filtered;
+ $lang = $iterator->current();
+ if(isset($changes['whatsNew'][$lang])) {
+ return $filtered['whatsNew'][$lang];
}
- $isFirstCall = false;
- } while($lang !== 'en');
+ $iterator->next();
+ } while($lang !== 'en' && $iterator->valid());
return $filtered;
}
- protected function getLangTrunk(string $lang):string {
- $pos = strpos($lang, '_');
- if($pos !== false) {
- $lang = substr($lang, 0, $pos);
- }
- return $lang;
- }
-
- protected function findWhatsNewTranslation(string $lang, array &$result, array $whatsNew): bool {
- if(isset($whatsNew[$lang])) {
- $result['whatsNew'] = $whatsNew[$lang];
- return true;
- }
- $trunkedLang = $this->getLangTrunk($lang);
- if($trunkedLang !== $lang && isset($whatsNew[$trunkedLang])) {
- $result['whatsNew'] = $whatsNew[$trunkedLang];
- return true;
- }
- return false;
- }
-
/**
* @param array $groupIds
* @return array
diff --git a/apps/user_ldap/lib/Connection.php b/apps/user_ldap/lib/Connection.php
index 85e6ad6fd9e..c912d9f89f8 100644
--- a/apps/user_ldap/lib/Connection.php
+++ b/apps/user_ldap/lib/Connection.php
@@ -576,8 +576,8 @@ class Connection extends LDAPUtility {
if (!$isOverrideMainServer) {
$this->doConnect($this->configuration->ldapHost,
$this->configuration->ldapPort);
+ return $this->bind();
}
- return $this->bind();
} catch (ServerNotAvailableException $e) {
if(!$isBackupHost) {
throw $e;
diff --git a/apps/user_ldap/tests/ConnectionTest.php b/apps/user_ldap/tests/ConnectionTest.php
index c6c1fe11922..7a5da72fcdb 100644
--- a/apps/user_ldap/tests/ConnectionTest.php
+++ b/apps/user_ldap/tests/ConnectionTest.php
@@ -110,7 +110,7 @@ class ConnectionTest extends \Test\TestCase {
->method('setOption')
->will($this->returnValue(true));
- $this->ldap->expects($this->exactly(2))
+ $this->ldap->expects($this->exactly(3))
->method('connect')
->will($this->returnValue('ldapResource'));
@@ -119,7 +119,7 @@ class ConnectionTest extends \Test\TestCase {
->will($this->returnValue(0));
// Not called often enough? Then, the fallback to the backup server is broken.
- $this->connection->expects($this->exactly(3))
+ $this->connection->expects($this->exactly(4))
->method('getFromCache')
->with('overrideMainServer')
->will($this->onConsecutiveCalls(false, false, true, true));
diff --git a/config/config.sample.php b/config/config.sample.php
index 5c6ca58a640..2dddd5a7da8 100644
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -917,7 +917,7 @@ $CONFIG = array(
*/
'preview_office_cl_parameters' =>
' --headless --nologo --nofirststartwizard --invisible --norestore '.
- '--convert-to pdf --outdir ',
+ '--convert-to png --outdir ',
/**
* Only register providers that have been explicitly enabled
diff --git a/core/Controller/WhatsNewController.php b/core/Controller/WhatsNewController.php
new file mode 100644
index 00000000000..c3a6d28cea2
--- /dev/null
+++ b/core/Controller/WhatsNewController.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.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 OC\Core\Controller;
+
+use OC\CapabilitiesManager;
+use OC\Security\IdentityProof\Manager;
+use OC\Updater\ChangesCheck;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\Defaults;
+use OCP\IConfig;
+use OCP\IRequest;
+use OCP\IUserManager;
+use OCP\IUserSession;
+use OCP\L10N\IFactory;
+
+class WhatsNewController extends OCSController {
+
+ /** @var IConfig */
+ protected $config;
+ /** @var IUserSession */
+ private $userSession;
+ /** @var ChangesCheck */
+ private $whatsNewService;
+ /** @var IFactory */
+ private $langFactory;
+ /** @var Defaults */
+ private $defaults;
+
+ public function __construct(
+ string $appName,
+ IRequest $request,
+ CapabilitiesManager $capabilitiesManager,
+ IUserSession $userSession,
+ IUserManager $userManager,
+ Manager $keyManager,
+ IConfig $config,
+ ChangesCheck $whatsNewService,
+ IFactory $langFactory,
+ Defaults $defaults
+ ) {
+ parent::__construct($appName, $request, $capabilitiesManager, $userSession, $userManager, $keyManager);
+ $this->config = $config;
+ $this->userSession = $userSession;
+ $this->whatsNewService = $whatsNewService;
+ $this->langFactory = $langFactory;
+ $this->defaults = $defaults;
+ }
+
+ /**
+ * @NoAdminRequired
+ */
+ public function get():DataResponse {
+ $user = $this->userSession->getUser();
+ if($user === null) {
+ throw new \RuntimeException("Acting user cannot be resolved");
+ }
+ $lastRead = $this->config->getUserValue($user->getUID(), 'core', 'whatsNewLastRead', 0);
+ $currentVersion = $this->whatsNewService->normalizeVersion($this->config->getSystemValue('version'));
+
+ if(version_compare($lastRead, $currentVersion, '>=')) {
+ return new DataResponse([], Http::STATUS_NO_CONTENT);
+ }
+
+ try {
+ $iterator = $this->langFactory->getLanguageIterator();
+ $whatsNew = $this->whatsNewService->getChangesForVersion($currentVersion);
+ $resultData = [
+ 'changelogURL' => $whatsNew['changelogURL'],
+ 'product' => $this->defaults->getName(),
+ 'version' => $currentVersion,
+ ];
+ do {
+ $lang = $iterator->current();
+ if(isset($whatsNew['whatsNew'][$lang])) {
+ $resultData['whatsNew'] = $whatsNew['whatsNew'][$lang];
+ break;
+ }
+ $iterator->next();
+ } while ($lang !== 'en' && $iterator->valid());
+ return new DataResponse($resultData);
+ } catch (DoesNotExistException $e) {
+ return new DataResponse([], Http::STATUS_NO_CONTENT);
+ }
+ }
+
+ /**
+ * @NoAdminRequired
+ *
+ * @throws \OCP\PreConditionNotMetException
+ * @throws DoesNotExistException
+ */
+ public function dismiss(string $version):DataResponse {
+ $user = $this->userSession->getUser();
+ if($user === null) {
+ throw new \RuntimeException("Acting user cannot be resolved");
+ }
+ $version = $this->whatsNewService->normalizeVersion($version);
+ // checks whether it's a valid version, throws an Exception otherwise
+ $this->whatsNewService->getChangesForVersion($version);
+ $this->config->setUserValue($user->getUID(), 'core', 'whatsNewLastRead', $version);
+ return new DataResponse();
+ }
+}
diff --git a/core/css/guest.css b/core/css/guest.css
index a5f6b57533f..75ad1a787da 100644
--- a/core/css/guest.css
+++ b/core/css/guest.css
@@ -166,7 +166,8 @@ form #datadirField legend {
input, textarea, select, button, div[contenteditable=true] {
font-family: 'Open Sans', Frutiger, Calibri, 'Myriad Pro', Myriad, sans-serif;
}
-input {
+input,
+input:not([type='range']) {
font-size: 20px;
margin: 5px;
padding: 11px 10px 9px;
@@ -175,6 +176,7 @@ input {
-webkit-appearance: none;
}
input[type='submit'],
+input[type='submit'].icon-confirm,
input[type='button'],
button, .button,
select {
@@ -207,6 +209,7 @@ input.login {
background-position: right 16px center;
}
input[type='submit'],
+input[type='submit'].icon-confirm,
input.updateButton,
input.update-continue {
padding: 10px 20px; /* larger log in and installation buttons */
diff --git a/core/css/mobile.scss b/core/css/mobile.scss
index f3b89ddb48c..116d174989c 100644
--- a/core/css/mobile.scss
+++ b/core/css/mobile.scss
@@ -1,16 +1,5 @@
@media only screen and (max-width: 768px) {
-#body-login #header {
- padding-top: 10px;
-}
-
-#body-login .wrapper {
- display: flex;
- flex-direction: row;
- align-self: center;
- align-items: center;
-}
-
/* do not show update notification on mobile */
#update-notification {
display: none !important;
diff --git a/core/css/publicshareauth.css b/core/css/publicshareauth.css
index 7f83e0b41e7..2f7622ea221 100644
--- a/core/css/publicshareauth.css
+++ b/core/css/publicshareauth.css
@@ -14,7 +14,8 @@ form fieldset {
min-width: 0; /* FF hack for to override default value */
}
-input[type='submit'] {
+input[type='submit'],
+input[type='submit'].icon-confirm {
width: 45px;
height: 45px;
margin-left: 0 !important;
diff --git a/core/css/styles.scss b/core/css/styles.scss
index 1938eb79afd..6ff8d30a590 100644
--- a/core/css/styles.scss
+++ b/core/css/styles.scss
@@ -92,15 +92,6 @@ body {
height: auto;
}
-#body-login {
- text-align: center;
- background-color: var(--color-primary);
- background-image: url('../img/background.png?v=2');
- background-position: 50% 50%;
- background-repeat: no-repeat;
- background-size: cover;
-}
-
.two-factor-header {
text-align: center;
}
@@ -125,11 +116,6 @@ body {
display: none;
}
-#body-login .float-spinner {
- margin-top: -32px;
- padding-top: 32px;
-}
-
#nojavascript {
position: fixed;
top: 0;
@@ -332,135 +318,10 @@ body {
/* LOG IN & INSTALLATION ------------------------------------------------------------ */
-/* Some whitespace to the top */
-
-#body-login {
- #header {
- padding-top: 100px;
- }
- background-attachment: fixed;
- /* fix background gradient */
- height: 100%;
- /* fix sticky footer */
- p.info, form fieldset legend, #datadirContent label {
- text-align: center;
- color: var(--color-primary-text);
- }
- form {
- fieldset .warning-info, input[type='checkbox'] + label {
- text-align: center;
- color: var(--color-primary-text);
- }
- .warning input[type='checkbox'] {
- &:hover + label, &:focus + label, + label {
- color: var(--color-primary-text) !important;
- }
- }
- }
- .update {
- h2 {
- margin: 0 0 20px;
- }
- a {
- color: var(--color-primary-text);
- border-bottom: 1px solid var(--color-background-darker);
- }
- }
- .infogroup {
- margin-bottom: 15px;
- }
- p#message img {
- vertical-align: middle;
- padding: 5px;
- }
- div.buttons {
- text-align: center;
- }
- p.info {
- margin: 0 auto;
- padding-top: 20px;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- a {
- font-weight: 600;
- padding: 13px;
- margin: -13px;
- }
- }
- form {
- position: relative;
- width: 280px;
- margin: 16px auto;
- padding: 0;
- fieldset {
- margin-bottom: 20px;
- text-align: left;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- }
- #sqliteInformation {
- margin-top: -20px;
- margin-bottom: 20px;
- }
- #adminaccount {
- margin-bottom: 15px;
- }
- fieldset legend {
- width: 100%;
- }
- }
-}
-
-/* Dark subtle label text */
-
-/* overrides another !important statement that sets this to unreadable black */
-
#datadirContent label {
width: 100%;
}
-#body-login {
- #datadirContent label {
- display: block;
- margin: 0;
- }
- form #datadirField legend {
- margin-bottom: 15px;
- }
- #showAdvanced {
- padding: 13px;
- /* increase clickable area of Advanced dropdown */
- img {
- vertical-align: bottom;
- /* adjust position of Advanced dropdown arrow */
- margin-left: -4px;
- }
- }
- .icon-info-white {
- padding: 10px;
- }
- .strengthify-wrapper {
- display: inline-block;
- position: relative;
- left: 5px;
- top: -20px;
- width: 269px;
- border-radius: 0 0 2px 2px;
- overflow: hidden;
- height: 3px;
- }
- input {
- &[type='text'], &[type='password'], &[type='email'] {
- border: none;
- font-weight: 300;
- }
- }
-}
-
/* strengthify wrapper */
/* General new input field look */
@@ -475,88 +336,12 @@ body {
user-select: none;
}
-#body-login .grouptop input, .grouptop input {
- margin-bottom: 0 !important;
- border-bottom: 0 !important;
- border-bottom-left-radius: 0 !important;
- border-bottom-right-radius: 0 !important;
-}
-
-#body-login .groupmiddle input, .groupmiddle input {
- margin-top: 0 !important;
- margin-bottom: 0 !important;
- border-top: 0 !important;
- border-bottom: 0 !important;
- border-radius: 0 !important;
-}
-
-#body-login .groupbottom input, .groupbottom input {
- margin-top: 0 !important;
- border-top: 0 !important;
- border-top-right-radius: 0 !important;
- border-top-left-radius: 0 !important;
-}
-
-#body-login .groupbottom input[type=submit] {
- box-shadow: none !important;
-}
-
/* keep the labels for screen readers but hide them since we use placeholders */
label.infield {
display: none;
}
-#body-login {
- form {
- input[type='checkbox'] + label {
- position: relative;
- margin: 0;
- padding: 14px;
- vertical-align: middle;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- }
- .errors {
- border: 1px solid var(--color-error);
- list-style-indent: inside;
- margin: 0 0 2em;
- padding: 1em;
- }
- }
- .success {
- border: 1px solid var(--color-success);
- width: 35%;
- margin: 30px auto;
- padding: 1em;
- text-align: center;
- }
- #showAdvanced > img {
- padding: 4px;
- box-sizing: border-box;
- }
- p.info a, #showAdvanced {
- color: var(--color-primary-text);
- }
- #remember_login {
- &:hover + label, &:focus + label {
- opacity: .6;
- }
- }
- #forgot-password {
- &:hover, &:focus {
- opacity: .6;
- }
- }
- p.info a {
- &:hover, &:focus {
- opacity: .6;
- }
- }
-}
-
/* Show password toggle */
#show, #dbpassword {
@@ -611,60 +396,6 @@ label.infield {
padding: 6px 4px;
}
-/* Database selector */
-#body-login {
- form #selectDbType {
- text-align: center;
- white-space: nowrap;
- margin: 0;
- .info {
- white-space: normal;
- }
- label {
- position: static;
- margin: 0 -3px 5px;
- font-size: 12px;
- background: var(--color-background-dark);
- color: var(--color-text-lighter);
- cursor: pointer;
- border: 1px solid var(--color-border-dark);
- span {
- cursor: pointer;
- padding: 10px 20px;
- }
- &.ui-state-hover, &.ui-state-active {
- color: var(--color-main-text);
- background-color: var(--color-border);
- }
- }
- }
- .warning, .update, .error {
- display: block;
- padding: 10px;
- background-color: var(--color-background-darker);
- color: var(--color-primary-text);
- text-align: left;
- border-radius: var(--border-radius);
- cursor: default;
- }
- .update {
- width: inherit;
- text-align: center;
- .appList {
- list-style: disc;
- text-align: left;
- margin-left: 25px;
- margin-right: 25px;
- }
- }
- .v-align {
- width: inherit;
- }
- .update img.float-spinner {
- float: left;
- }
-}
-
/* Warnings and errors are the same */
#body-user .warning, #body-settings .warning {
@@ -708,27 +439,6 @@ label.infield {
border-color: var(--color-error) !important;
}
-/* Fixes for log in page, TODO should be removed some time */
-
-#body-login {
- ul.error-wide {
- margin-top: 35px;
- }
- .warning {
- margin: 0 7px 5px 4px;
- legend {
- opacity: 1;
- }
- }
- a.warning {
- cursor: pointer;
- }
- .updateProgress .error {
- margin-top: 10px;
- margin-bottom: 10px;
- }
-}
-
/* fixes for update page TODO should be fixed some time in a proper way */
/* this is just for an error while updating the ownCloud instance */
@@ -747,72 +457,10 @@ label.infield {
/* Log in and install button */
-#body-login #submit-wrapper {
- position: relative; /* Make the wrapper the containing block of its
- absolutely positioned descendant icons */
-
- .icon-confirm-white {
- position: absolute;
- top: 23px;
- right: 23px;
- }
- .icon-loading-small {
- position: absolute;
- top: 22px;
- right: 24px;
- }
-
- #submit-icon {
- pointer-events: none; /* The submit icon is positioned on the submit
- button. From the user point of view the icon is
- part of the button, so the clicks on the icon
- have to be applied to the button instead. */
- }
-}
-
-#body-login input {
- font-size: 20px;
- margin: 5px;
- padding: 10px 10px 8px;
- &[type='text'], &[type='password'] {
- width: calc(100% - 10px); /* 5px margin */
- }
- &.login {
- width: 269px;
- background-position: right 16px center;
- }
- &[type='submit'] {
- padding: 10px 20px;
- /* larger log in and installation buttons */
- }
-}
-
#remember_login {
margin: 18px 5px 0 16px !important;
}
-#body-login {
- .remember-login-container {
- display: inline-block;
- margin: 10px 0;
- text-align: center;
- width: 100%;
- }
- #forgot-password {
- padding: 11px;
- float: right;
- color: var(--color-primary-text);
- }
- .wrapper {
- min-height: 100%;
- margin: 0 auto -70px;
- width: 300px;
- }
- footer, .push {
- height: 70px;
- }
-}
-
/* Sticky footer */
/* round profile photos */
diff --git a/core/css/whatsnew.scss b/core/css/whatsnew.scss
new file mode 100644
index 00000000000..1c2ab08333a
--- /dev/null
+++ b/core/css/whatsnew.scss
@@ -0,0 +1,31 @@
+/**
+ * @copyright Copyright (c) 2018, Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ */
+
+.whatsNewPopover {
+ bottom: 35px !important;
+ left: 15px !important;
+ width: 270px;
+ background-color: var(--color-background-dark);
+}
+
+.whatsNewPopover p {
+ width: auto !important;
+}
+
+.whatsNewPopover .caption {
+ font-weight: bolder;
+ cursor: auto !important;
+}
+
+.whatsNewPopover .icon-close {
+ position: absolute;
+ right: 0;
+}
+
+.whatsNewPopover::after {
+ content: none;
+}
diff --git a/core/js/core.json b/core/js/core.json
index 41b927147b6..502e3a57976 100644
--- a/core/js/core.json
+++ b/core/js/core.json
@@ -48,6 +48,7 @@
"public/appconfig.js",
"public/comments.js",
"public/publicpage.js",
+ "public/whatsnew.js",
"multiselect.js",
"oc-requesttoken.js",
"setupchecks.js",
diff --git a/core/js/merged-template-prepend.json b/core/js/merged-template-prepend.json
index f4ef511bc78..c274201d97e 100644
--- a/core/js/merged-template-prepend.json
+++ b/core/js/merged-template-prepend.json
@@ -7,6 +7,7 @@
"eventsource.js",
"public/appconfig.js",
"public/comments.js",
+ "public/whatsnew.js",
"config.js",
"oc-requesttoken.js",
"apps.js",
diff --git a/core/js/public/whatsnew.js b/core/js/public/whatsnew.js
new file mode 100644
index 00000000000..20a871ada27
--- /dev/null
+++ b/core/js/public/whatsnew.js
@@ -0,0 +1,134 @@
+/**
+ * @copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ */
+
+(function(OCP) {
+ "use strict";
+
+ OCP.WhatsNew = {
+
+ query: function(options) {
+ options = options || {};
+ var dismissOptions = options.dismiss || {};
+ $.ajax({
+ type: 'GET',
+ url: options.url || OC.linkToOCS('core', 2) + 'whatsnew?format=json',
+ success: options.success || function(data, statusText, xhr) {
+ OCP.WhatsNew._onQuerySuccess(data, statusText, xhr, dismissOptions);
+ },
+ error: options.error || this._onQueryError
+ });
+ },
+
+ dismiss: function(version, options) {
+ options = options || {};
+ $.ajax({
+ type: 'POST',
+ url: options.url || OC.linkToOCS('core', 2) + 'whatsnew',
+ data: {version: encodeURIComponent(version)},
+ success: options.success || this._onDismissSuccess,
+ error: options.error || this._onDismissError
+ });
+ // remove element immediately
+ $('.whatsNewPopover').remove();
+ },
+
+ _onQuerySuccess: function(data, statusText, xhr, dismissOptions) {
+ console.debug('querying Whats New data was successful: ' + statusText);
+ console.debug(data);
+
+ if(xhr.status !== 200) {
+ return;
+ }
+
+ var item, menuItem, text, icon;
+
+ var div = document.createElement('div');
+ div.classList.add('popovermenu', 'open', 'whatsNewPopover', 'menu-left');
+
+ var list = document.createElement('ul');
+
+ // header
+ item = document.createElement('li');
+ menuItem = document.createElement('span');
+ menuItem.className = "menuitem";
+
+ text = document.createElement('span');
+ text.innerText = t('core', 'New in') + ' ' + data['ocs']['data']['product'];
+ text.className = 'caption';
+ menuItem.appendChild(text);
+
+ icon = document.createElement('span');
+ icon.className = 'icon-close';
+ icon.onclick = function () {
+ OCP.WhatsNew.dismiss(data['ocs']['data']['version'], dismissOptions);
+ };
+ menuItem.appendChild(icon);
+
+ item.appendChild(menuItem);
+ list.appendChild(item);
+
+ // Highlights
+ for (var i in data['ocs']['data']['whatsNew']['regular']) {
+ var whatsNewTextItem = data['ocs']['data']['whatsNew']['regular'][i];
+ item = document.createElement('li');
+
+ menuItem = document.createElement('span');
+ menuItem.className = "menuitem";
+
+ icon = document.createElement('span');
+ icon.className = 'icon-star-dark';
+ menuItem.appendChild(icon);
+
+ text = document.createElement('p');
+ text.innerHTML = _.escape(whatsNewTextItem);
+ menuItem.appendChild(text);
+
+ item.appendChild(menuItem);
+ list.appendChild(item);
+ }
+
+ // Changelog URL
+ if(!_.isUndefined(data['ocs']['data']['changelogURL'])) {
+ item = document.createElement('li');
+
+ menuItem = document.createElement('a');
+ menuItem.href = data['ocs']['data']['changelogURL'];
+ menuItem.rel = 'noreferrer noopener';
+ menuItem.target = '_blank';
+
+ icon = document.createElement('span');
+ icon.className = 'icon-link';
+ menuItem.appendChild(icon);
+
+ text = document.createElement('span');
+ text.innerText = t('core', 'View changelog');
+ menuItem.appendChild(text);
+
+ item.appendChild(menuItem);
+ list.appendChild(item);
+ }
+
+ div.appendChild(list);
+ document.body.appendChild(div);
+ },
+
+ _onQueryError: function (x, t, e) {
+ console.debug('querying Whats New Data resulted in an error: ' + t + e);
+ console.debug(x);
+ },
+
+ _onDismissSuccess: function(data) {
+ //noop
+ },
+
+ _onDismissError: function (data) {
+ console.debug('dismissing Whats New data resulted in an error: ' + data);
+ }
+ };
+})(OCP);
diff --git a/core/js/sharedialogresharerinfoview.js b/core/js/sharedialogresharerinfoview.js
index 8afec33e7eb..f4bf9afa0b2 100644
--- a/core/js/sharedialogresharerinfoview.js
+++ b/core/js/sharedialogresharerinfoview.js
@@ -84,7 +84,18 @@
undefined,
{escape: false}
);
- } else {
+ } else if (this.model.getReshareType() === OC.Share.SHARE_TYPE_CIRCLE) {
+ sharedByText = t(
+ 'core',
+ 'Shared with you and {circle} by {owner}',
+ {
+ circle: this.model.getReshareWithDisplayName(),
+ owner: ownerDisplayName
+ },
+ undefined,
+ {escape: false}
+ );
+ } else {
sharedByText = t(
'core',
'Shared with you by {owner}',
diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js
index 0ff4c36b712..53a65fcdf7a 100644
--- a/core/js/sharedialogshareelistview.js
+++ b/core/js/sharedialogshareelistview.js
@@ -25,7 +25,7 @@
'<ul id="shareWithList" class="shareWithList">' +
'{{#each sharees}}' +
'<li data-share-id="{{shareId}}" data-share-type="{{shareType}}" data-share-with="{{shareWith}}">' +
- '<div class="avatar {{#if modSeed}}imageplaceholderseed{{/if}}" data-username="{{shareWith}}" data-displayname="{{shareWithDisplayName}}" {{#if modSeed}}data-seed="{{shareWith}} {{shareType}}"{{/if}}></div>' +
+ '<div class="avatar {{#if modSeed}}imageplaceholderseed{{/if}}" data-username="{{shareWith}}" data-avatar="{{shareWithAvatar}}" data-displayname="{{shareWithDisplayName}}" {{#if modSeed}}data-seed="{{shareWith}} {{shareType}}"{{/if}}></div>' +
'<span class="username" title="{{shareWithTitle}}">{{shareWithDisplayName}}</span>' +
'<span class="sharingOptionsGroup">' +
'{{#if editPermissionPossible}}' +
@@ -188,6 +188,7 @@
getShareeObject: function(shareIndex) {
var shareWith = this.model.getShareWith(shareIndex);
var shareWithDisplayName = this.model.getShareWithDisplayName(shareIndex);
+ var shareWithAvatar = this.model.getShareWithAvatar(shareIndex);
var shareWithTitle = '';
var shareType = this.model.getShareType(shareIndex);
var sharedBy = this.model.getSharedBy(shareIndex);
@@ -216,6 +217,10 @@
shareWithTitle = shareWith + " (" + t('core', 'email') + ')';
} else if (shareType === OC.Share.SHARE_TYPE_CIRCLE) {
shareWithTitle = shareWith;
+ // Force "shareWith" in the template to a safe value, as the
+ // original "shareWith" returned by the model may contain
+ // problematic characters like "'".
+ shareWith = 'circle-' + shareIndex;
}
if (sharedBy !== oc_current_user) {
@@ -243,10 +248,11 @@
hasDeletePermission: this.model.hasDeletePermission(shareIndex),
shareWith: shareWith,
shareWithDisplayName: shareWithDisplayName,
+ shareWithAvatar: shareWithAvatar,
shareWithTitle: shareWithTitle,
shareType: shareType,
shareId: this.model.get('shares')[shareIndex].id,
- modSeed: shareType !== OC.Share.SHARE_TYPE_USER && shareType !== OC.Share.SHARE_TYPE_CIRCLE,
+ modSeed: shareType !== OC.Share.SHARE_TYPE_USER && (shareType !== OC.Share.SHARE_TYPE_CIRCLE || shareWithAvatar),
isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE,
isRemoteGroupShare: shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP,
isMailShare: shareType === OC.Share.SHARE_TYPE_EMAIL,
@@ -357,9 +363,16 @@
this.$('.avatar').each(function () {
var $this = $(this);
+
if ($this.hasClass('imageplaceholderseed')) {
$this.css({width: 32, height: 32});
- $this.imageplaceholder($this.data('seed'));
+ if ($this.data('avatar')) {
+ $this.css('border-radius', '0%');
+ $this.css('background', 'url(' + $this.data('avatar') + ') no-repeat');
+ $this.css('background-size', '31px');
+ } else {
+ $this.imageplaceholder($this.data('seed'));
+ }
} else {
// user, size, ie8fix, hidedefault, callback, displayname
$this.avatar($this.data('username'), 32, undefined, undefined, undefined, $this.data('displayname'));
diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js
index e7824aca33a..93feba9c889 100644
--- a/core/js/shareitemmodel.js
+++ b/core/js/shareitemmodel.js
@@ -43,6 +43,7 @@
* @property {string} token
* @property {string} share_with
* @property {string} share_with_displayname
+ * @property {string} share_with_avatar
* @property {string} mail_send
* @property {Date} expiration optional?
* @property {number} stime optional?
@@ -405,6 +406,20 @@
return share.share_with_displayname;
},
+
+ /**
+ * @param shareIndex
+ * @returns {string}
+ */
+ getShareWithAvatar: function(shareIndex) {
+ /** @type OC.Share.Types.ShareInfo **/
+ var share = this.get('shares')[shareIndex];
+ if(!_.isObject(share)) {
+ throw "Unknown Share";
+ }
+ return share.share_with_avatar;
+ },
+
/**
* @param shareIndex
* @returns {string}
diff --git a/core/js/tests/specs/sharedialogviewSpec.js b/core/js/tests/specs/sharedialogviewSpec.js
index 83c89053202..5fd920a758c 100644
--- a/core/js/tests/specs/sharedialogviewSpec.js
+++ b/core/js/tests/specs/sharedialogviewSpec.js
@@ -427,7 +427,21 @@ describe('OC.Share.ShareDialogView', function() {
share_type: OC.Share.SHARE_TYPE_REMOTE,
share_with: 'foo@bar.com/baz',
share_with_displayname: 'foo@bar.com/baz'
-
+ },{
+ id: 103,
+ item_source: 123,
+ permissions: 31,
+ share_type: OC.Share.SHARE_TYPE_CIRCLE,
+ share_with: 'circle-0',
+ share_with_displayname: 'Circle (Personal circle, user0)',
+ share_with_avatar: 'path/to/the/avatar'
+ },{
+ id: 104,
+ item_source: 123,
+ permissions: 31,
+ share_type: OC.Share.SHARE_TYPE_CIRCLE,
+ share_with: 'circle-1',
+ share_with_displayname: 'Circle (Public circle, user0)',
}]
});
});
@@ -439,10 +453,10 @@ describe('OC.Share.ShareDialogView', function() {
});
it('test correct function calls', function() {
- expect(avatarStub.calledTwice).toEqual(true);
+ expect(avatarStub.calledThrice).toEqual(true);
expect(placeholderStub.callCount).toEqual(4);
- expect(dialog.$('.shareWithList').children().length).toEqual(3);
- expect(dialog.$('.avatar').length).toEqual(4);
+ expect(dialog.$('.shareWithList').children().length).toEqual(5);
+ expect(dialog.$('.avatar').length).toEqual(6);
});
it('test avatar owner', function() {
@@ -469,6 +483,20 @@ describe('OC.Share.ShareDialogView', function() {
expect(args.length).toEqual(1);
expect(args[0]).toEqual('foo@bar.com/baz ' + OC.Share.SHARE_TYPE_REMOTE);
});
+
+ it('test avatar for circle', function() {
+ var avatarElement = dialog.$('.avatar').eq(4);
+ expect(avatarElement.css('background')).toContain('path/to/the/avatar');
+ });
+
+ it('test avatar for circle without avatar', function() {
+ var args = avatarStub.getCall(2).args;
+ expect(args.length).toEqual(6);
+ // Note that "data-username" is set to "circle-{shareIndex}",
+ // not to the "shareWith" field.
+ expect(args[0]).toEqual('circle-4');
+ expect(args[5]).toEqual('Circle (Public circle, user0)');
+ });
});
});
describe('get suggestions', function() {
diff --git a/core/l10n/de.js b/core/l10n/de.js
index bfdd92899c7..924c559a441 100644
--- a/core/l10n/de.js
+++ b/core/l10n/de.js
@@ -105,6 +105,8 @@ OC.L10N.register(
"Pending" : "Ausstehend",
"Copy to {folder}" : "Kopieren nach {folder}",
"Move to {folder}" : "Verschieben nach {folder}",
+ "New in" : "Neu in",
+ "View changelog" : "Liste der Veränderungen anschauen",
"Very weak password" : "Sehr schwaches Passwort",
"Weak password" : "Schwaches Passwort",
"So-so password" : "Passables Passwort",
@@ -174,6 +176,7 @@ OC.L10N.register(
"Read only" : "Schreibgeschützt",
"File drop (upload only)" : "Dateien ablegen (nur Hochladen)",
"Shared with you and the group {group} by {owner}" : "{owner} hat dies mit Dir und der Gruppe {group} geteilt",
+ "Shared with you and {circle} by {owner}" : "Von {owner} mit Dir und {circle} geteilt",
"Shared with you by {owner}" : "{owner} hat dies mit Dir geteilt",
"Choose a password for the mail share" : "Wähle ein Passwort für das Teilen via E-Mail",
"{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} mittels Link geteilt",
diff --git a/core/l10n/de.json b/core/l10n/de.json
index 4073a19c921..7fd76747d4c 100644
--- a/core/l10n/de.json
+++ b/core/l10n/de.json
@@ -103,6 +103,8 @@
"Pending" : "Ausstehend",
"Copy to {folder}" : "Kopieren nach {folder}",
"Move to {folder}" : "Verschieben nach {folder}",
+ "New in" : "Neu in",
+ "View changelog" : "Liste der Veränderungen anschauen",
"Very weak password" : "Sehr schwaches Passwort",
"Weak password" : "Schwaches Passwort",
"So-so password" : "Passables Passwort",
@@ -172,6 +174,7 @@
"Read only" : "Schreibgeschützt",
"File drop (upload only)" : "Dateien ablegen (nur Hochladen)",
"Shared with you and the group {group} by {owner}" : "{owner} hat dies mit Dir und der Gruppe {group} geteilt",
+ "Shared with you and {circle} by {owner}" : "Von {owner} mit Dir und {circle} geteilt",
"Shared with you by {owner}" : "{owner} hat dies mit Dir geteilt",
"Choose a password for the mail share" : "Wähle ein Passwort für das Teilen via E-Mail",
"{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} mittels Link geteilt",
diff --git a/core/l10n/de_DE.js b/core/l10n/de_DE.js
index d22008181cf..e7a04e044df 100644
--- a/core/l10n/de_DE.js
+++ b/core/l10n/de_DE.js
@@ -105,6 +105,8 @@ OC.L10N.register(
"Pending" : "Ausstehend",
"Copy to {folder}" : "Kopieren nach {folder}",
"Move to {folder}" : "Verschieben nach {folder}",
+ "New in" : "Neu in",
+ "View changelog" : "Liste der Veränderungen anschauen",
"Very weak password" : "Sehr schwaches Passwort",
"Weak password" : "Schwaches Passwort",
"So-so password" : "Passables Passwort",
@@ -174,6 +176,7 @@ OC.L10N.register(
"Read only" : "Schreibgeschützt",
"File drop (upload only)" : "Dateien ablegen (nur Hochladen)",
"Shared with you and the group {group} by {owner}" : "Von {owner} mit Ihnen und der Gruppe {group} geteilt.",
+ "Shared with you and {circle} by {owner}" : "Von {owner} mit Ihnen und {circle} geteilt",
"Shared with you by {owner}" : "Von {owner} mit Ihnen geteilt.",
"Choose a password for the mail share" : "Wählen Sie ein Passwort für das Teilen via E-Mail",
"{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} mittels Link geteilt",
diff --git a/core/l10n/de_DE.json b/core/l10n/de_DE.json
index 904f8b5d934..752081ce166 100644
--- a/core/l10n/de_DE.json
+++ b/core/l10n/de_DE.json
@@ -103,6 +103,8 @@
"Pending" : "Ausstehend",
"Copy to {folder}" : "Kopieren nach {folder}",
"Move to {folder}" : "Verschieben nach {folder}",
+ "New in" : "Neu in",
+ "View changelog" : "Liste der Veränderungen anschauen",
"Very weak password" : "Sehr schwaches Passwort",
"Weak password" : "Schwaches Passwort",
"So-so password" : "Passables Passwort",
@@ -172,6 +174,7 @@
"Read only" : "Schreibgeschützt",
"File drop (upload only)" : "Dateien ablegen (nur Hochladen)",
"Shared with you and the group {group} by {owner}" : "Von {owner} mit Ihnen und der Gruppe {group} geteilt.",
+ "Shared with you and {circle} by {owner}" : "Von {owner} mit Ihnen und {circle} geteilt",
"Shared with you by {owner}" : "Von {owner} mit Ihnen geteilt.",
"Choose a password for the mail share" : "Wählen Sie ein Passwort für das Teilen via E-Mail",
"{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} mittels Link geteilt",
diff --git a/core/l10n/el.js b/core/l10n/el.js
index 0adde6674ce..194ff818c72 100644
--- a/core/l10n/el.js
+++ b/core/l10n/el.js
@@ -263,6 +263,7 @@ OC.L10N.register(
"Redirecting …" : "Γίνεται ανακατεύθυνση ...",
"New password" : "Νέο συνθηματικό",
"New Password" : "Νέο Συνθηματικό",
+ "The password is wrong. Try again." : "Το συνθηματικό είναι λανθασμένο. Δοκιμάστε ξανά.",
"Two-factor authentication" : "Πιστοποίηση Δύο-Παραγόντων",
"Enhanced security is enabled for your account. Please authenticate using a second factor." : "Έχει ενεργοποιηθεί βελτιωμένη ασφάλεια για τον λογαριασμό σας. Παρακαλώ πιστοποιήστε με την χρήση δεύτερου παράγοντα",
"Cancel log in" : "Ακύρωση εισόδου",
diff --git a/core/l10n/el.json b/core/l10n/el.json
index 99cf6c50fe5..190a26e80c3 100644
--- a/core/l10n/el.json
+++ b/core/l10n/el.json
@@ -261,6 +261,7 @@
"Redirecting …" : "Γίνεται ανακατεύθυνση ...",
"New password" : "Νέο συνθηματικό",
"New Password" : "Νέο Συνθηματικό",
+ "The password is wrong. Try again." : "Το συνθηματικό είναι λανθασμένο. Δοκιμάστε ξανά.",
"Two-factor authentication" : "Πιστοποίηση Δύο-Παραγόντων",
"Enhanced security is enabled for your account. Please authenticate using a second factor." : "Έχει ενεργοποιηθεί βελτιωμένη ασφάλεια για τον λογαριασμό σας. Παρακαλώ πιστοποιήστε με την χρήση δεύτερου παράγοντα",
"Cancel log in" : "Ακύρωση εισόδου",
diff --git a/core/l10n/es.js b/core/l10n/es.js
index edfb25ff1ae..5cebd2a241a 100644
--- a/core/l10n/es.js
+++ b/core/l10n/es.js
@@ -105,6 +105,8 @@ OC.L10N.register(
"Pending" : "Pendiente",
"Copy to {folder}" : "Copiar a {folder}",
"Move to {folder}" : "Mover a {folder}",
+ "New in" : "Nuevo en",
+ "View changelog" : "Ver registro de cambios",
"Very weak password" : "Contraseña muy débil",
"Weak password" : "Contraseña débil",
"So-so password" : "Contraseña pasable",
@@ -131,6 +133,7 @@ OC.L10N.register(
"The reverse proxy header configuration is incorrect, or you are accessing Nextcloud from a trusted proxy. If not, this is a security issue and can allow an attacker to spoof their IP address as visible to the Nextcloud. Further information can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>." : "La configuración de cabeceras del proxy inverso es incorrecta, o estás accediendo a Nextcloud desde un proxy fiable. Si no, esto es un problema de seguridad que puede permitir que un atacante disfrazar su dirección IP como visible a Nextcloud. Se puede encontrar más información en la <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentación</a>.",
"Memcached is configured as distributed cache, but the wrong PHP module \"memcache\" is installed. \\OC\\Memcache\\Memcached only supports \"memcached\" and not \"memcache\". See the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{wikiLink}\">memcached wiki about both modules</a>." : "Memcached está configurado como caché distribuida, pero el módulo erróneo de PHP \"memcache\" está instalado. \\OC\\Memcache\\Memcached solo soporta \"memcached\" y no \"memcache\". Vea la <a target=\"_blank\" href=\"{wikiLink}\">wiki de memcached sobre ambos módulos</a>.",
"Some files have not passed the integrity check. Further information on how to resolve this issue can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>. (<a href=\"{codeIntegrityDownloadEndpoint}\">List of invalid files…</a> / <a href=\"{rescanEndpoint}\">Rescan…</a>)" : "Algunos archivos no han pasado la comprobación de integridad. Se puede encontrar más información sobre cómo resolver este problema en la <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentación</a>. (<a href=\"{codeIntegrityDownloadEndpoint}\">Lista de archivos inválidos...</a> / <a href=\"{rescanEndpoint}\">Reescanear</a>)",
+ "The PHP OPcache module is not loaded. <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">For better performance it is recommended</a> to load it into your PHP installation." : "El módulo PHP OPcache no está cargado. <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">Para mejorar el rendimiento se recomienda</a> cargarlo en tu instalación de PHP.",
"The PHP OPcache is not properly configured. <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">For better performance it is recommended</a> to use the following settings in the <code>php.ini</code>:" : "La OPcache de PHP no está bien configurada. <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">Para mejorar el rendimiento se recomienda</a> usar las siguientes configuraciones en el <code>php.ini</code>:",
"The PHP function \"set_time_limit\" is not available. This could result in scripts being halted mid-execution, breaking your installation. Enabling this function is strongly recommended." : "La función PHP \"set_time_limit\" no está disponible. Esto podría resultar en scripts detenidos a mitad de ejecución, rompiendo tu instalación. Activar esta función está fuertemente recomendado.",
"Your PHP does not have FreeType support, resulting in breakage of profile pictures and the settings interface." : "Tu PHP no tiene soporte FreeType, lo que provoca una rotura en las imágenes de perfil y en la interfaz de los ajustes.",
@@ -173,11 +176,13 @@ OC.L10N.register(
"Read only" : "Solo lectura",
"File drop (upload only)" : "Entrega de archivos (solo subida)",
"Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}",
+ "Shared with you and {circle} by {owner}" : "Compartido contigo y {circle} por {owner}",
"Shared with you by {owner}" : "Compartido contigo por {owner}",
"Choose a password for the mail share" : "Elija una contraseña para compartir por correo electrónico",
"{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} compartido por medio de un link",
"group" : "grupo",
"remote" : "remoto",
+ "remote group" : "grupo remoto",
"email" : "email",
"shared by {sharer}" : "compartido por {sharer}",
"Unshare" : "Dejar de compartir",
@@ -198,6 +203,7 @@ OC.L10N.register(
"An error occurred. Please try again" : "Ha ocurrido un error. Por favor inténtelo de nuevo",
"{sharee} (group)" : "{sharee} (grupo)",
"{sharee} (remote)" : "{sharee} (remoto)",
+ "{sharee} (remote group)" : "{sharee} (grupo remoto)",
"{sharee} (email)" : "{sharee} (email)",
"{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})",
"Share" : "Compartir",
diff --git a/core/l10n/es.json b/core/l10n/es.json
index 2f91abdeb35..38d48229b63 100644
--- a/core/l10n/es.json
+++ b/core/l10n/es.json
@@ -103,6 +103,8 @@
"Pending" : "Pendiente",
"Copy to {folder}" : "Copiar a {folder}",
"Move to {folder}" : "Mover a {folder}",
+ "New in" : "Nuevo en",
+ "View changelog" : "Ver registro de cambios",
"Very weak password" : "Contraseña muy débil",
"Weak password" : "Contraseña débil",
"So-so password" : "Contraseña pasable",
@@ -129,6 +131,7 @@
"The reverse proxy header configuration is incorrect, or you are accessing Nextcloud from a trusted proxy. If not, this is a security issue and can allow an attacker to spoof their IP address as visible to the Nextcloud. Further information can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>." : "La configuración de cabeceras del proxy inverso es incorrecta, o estás accediendo a Nextcloud desde un proxy fiable. Si no, esto es un problema de seguridad que puede permitir que un atacante disfrazar su dirección IP como visible a Nextcloud. Se puede encontrar más información en la <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentación</a>.",
"Memcached is configured as distributed cache, but the wrong PHP module \"memcache\" is installed. \\OC\\Memcache\\Memcached only supports \"memcached\" and not \"memcache\". See the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{wikiLink}\">memcached wiki about both modules</a>." : "Memcached está configurado como caché distribuida, pero el módulo erróneo de PHP \"memcache\" está instalado. \\OC\\Memcache\\Memcached solo soporta \"memcached\" y no \"memcache\". Vea la <a target=\"_blank\" href=\"{wikiLink}\">wiki de memcached sobre ambos módulos</a>.",
"Some files have not passed the integrity check. Further information on how to resolve this issue can be found in the <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentation</a>. (<a href=\"{codeIntegrityDownloadEndpoint}\">List of invalid files…</a> / <a href=\"{rescanEndpoint}\">Rescan…</a>)" : "Algunos archivos no han pasado la comprobación de integridad. Se puede encontrar más información sobre cómo resolver este problema en la <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">documentación</a>. (<a href=\"{codeIntegrityDownloadEndpoint}\">Lista de archivos inválidos...</a> / <a href=\"{rescanEndpoint}\">Reescanear</a>)",
+ "The PHP OPcache module is not loaded. <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">For better performance it is recommended</a> to load it into your PHP installation." : "El módulo PHP OPcache no está cargado. <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">Para mejorar el rendimiento se recomienda</a> cargarlo en tu instalación de PHP.",
"The PHP OPcache is not properly configured. <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">For better performance it is recommended</a> to use the following settings in the <code>php.ini</code>:" : "La OPcache de PHP no está bien configurada. <a target=\"_blank\" rel=\"noreferrer noopener\" href=\"{docLink}\">Para mejorar el rendimiento se recomienda</a> usar las siguientes configuraciones en el <code>php.ini</code>:",
"The PHP function \"set_time_limit\" is not available. This could result in scripts being halted mid-execution, breaking your installation. Enabling this function is strongly recommended." : "La función PHP \"set_time_limit\" no está disponible. Esto podría resultar en scripts detenidos a mitad de ejecución, rompiendo tu instalación. Activar esta función está fuertemente recomendado.",
"Your PHP does not have FreeType support, resulting in breakage of profile pictures and the settings interface." : "Tu PHP no tiene soporte FreeType, lo que provoca una rotura en las imágenes de perfil y en la interfaz de los ajustes.",
@@ -171,11 +174,13 @@
"Read only" : "Solo lectura",
"File drop (upload only)" : "Entrega de archivos (solo subida)",
"Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}",
+ "Shared with you and {circle} by {owner}" : "Compartido contigo y {circle} por {owner}",
"Shared with you by {owner}" : "Compartido contigo por {owner}",
"Choose a password for the mail share" : "Elija una contraseña para compartir por correo electrónico",
"{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} compartido por medio de un link",
"group" : "grupo",
"remote" : "remoto",
+ "remote group" : "grupo remoto",
"email" : "email",
"shared by {sharer}" : "compartido por {sharer}",
"Unshare" : "Dejar de compartir",
@@ -196,6 +201,7 @@
"An error occurred. Please try again" : "Ha ocurrido un error. Por favor inténtelo de nuevo",
"{sharee} (group)" : "{sharee} (grupo)",
"{sharee} (remote)" : "{sharee} (remoto)",
+ "{sharee} (remote group)" : "{sharee} (grupo remoto)",
"{sharee} (email)" : "{sharee} (email)",
"{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})",
"Share" : "Compartir",
diff --git a/core/l10n/fr.js b/core/l10n/fr.js
index 7fe5564c157..0eec26c6056 100644
--- a/core/l10n/fr.js
+++ b/core/l10n/fr.js
@@ -105,6 +105,7 @@ OC.L10N.register(
"Pending" : "En attente",
"Copy to {folder}" : "Copier vers {folder}",
"Move to {folder}" : "Déplacer vers {folder}",
+ "View changelog" : "Voir le journal des modifications",
"Very weak password" : "Mot de passe très faible",
"Weak password" : "Mot de passe faible",
"So-so password" : "Mot de passe tout juste acceptable",
@@ -172,11 +173,13 @@ OC.L10N.register(
"Read only" : "Lecture seule",
"File drop (upload only)" : "Dépôt de fichier (téléversement uniquement)",
"Shared with you and the group {group} by {owner}" : "Partagé avec vous et le groupe {group} par {owner}",
+ "Shared with you and {circle} by {owner}" : "Partagé avec vous et {circle} par {owner}",
"Shared with you by {owner}" : "Partagé avec vous par {owner}",
"Choose a password for the mail share" : "Choisissez un mot de passe pour le partage par email",
"{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} a partagé via un lien",
"group" : "groupe",
"remote" : "distant",
+ "remote group" : "groupe distant",
"email" : "Adresse de courriel",
"shared by {sharer}" : "partagé par {sharer}",
"Unshare" : "Ne plus partager",
@@ -197,6 +200,7 @@ OC.L10N.register(
"An error occurred. Please try again" : "Une erreur est survenue. Merci de réessayer",
"{sharee} (group)" : "{sharee} (groupe)",
"{sharee} (remote)" : "{sharee} (distant)",
+ "{sharee} (remote group)" : "{sharee} (groupe distant)",
"{sharee} (email)" : "{sharee} (email)",
"{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})",
"Share" : "Partager",
diff --git a/core/l10n/fr.json b/core/l10n/fr.json
index 085ef60cb2e..572d06610f4 100644
--- a/core/l10n/fr.json
+++ b/core/l10n/fr.json
@@ -103,6 +103,7 @@
"Pending" : "En attente",
"Copy to {folder}" : "Copier vers {folder}",
"Move to {folder}" : "Déplacer vers {folder}",
+ "View changelog" : "Voir le journal des modifications",
"Very weak password" : "Mot de passe très faible",
"Weak password" : "Mot de passe faible",
"So-so password" : "Mot de passe tout juste acceptable",
@@ -170,11 +171,13 @@
"Read only" : "Lecture seule",
"File drop (upload only)" : "Dépôt de fichier (téléversement uniquement)",
"Shared with you and the group {group} by {owner}" : "Partagé avec vous et le groupe {group} par {owner}",
+ "Shared with you and {circle} by {owner}" : "Partagé avec vous et {circle} par {owner}",
"Shared with you by {owner}" : "Partagé avec vous par {owner}",
"Choose a password for the mail share" : "Choisissez un mot de passe pour le partage par email",
"{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} a partagé via un lien",
"group" : "groupe",
"remote" : "distant",
+ "remote group" : "groupe distant",
"email" : "Adresse de courriel",
"shared by {sharer}" : "partagé par {sharer}",
"Unshare" : "Ne plus partager",
@@ -195,6 +198,7 @@
"An error occurred. Please try again" : "Une erreur est survenue. Merci de réessayer",
"{sharee} (group)" : "{sharee} (groupe)",
"{sharee} (remote)" : "{sharee} (distant)",
+ "{sharee} (remote group)" : "{sharee} (groupe distant)",
"{sharee} (email)" : "{sharee} (email)",
"{sharee} ({type}, {owner})" : "{sharee} ({type}, {owner})",
"Share" : "Partager",
diff --git a/core/l10n/hr.js b/core/l10n/hr.js
new file mode 100644
index 00000000000..66b30db8b30
--- /dev/null
+++ b/core/l10n/hr.js
@@ -0,0 +1,229 @@
+OC.L10N.register(
+ "core",
+ {
+ "Please select a file." : "Molimo odaberite datoteku.",
+ "File is too big" : "Datoteka je prevelika",
+ "The selected file is not an image." : "Odabrana datoteka nije slika.",
+ "The selected file cannot be read." : "Nije moguće pročitati odabranu datoteku.",
+ "Invalid file provided" : "Nevažeća datoteka",
+ "No image or file provided" : "Nijedna slika ili datoteka nije dobavljena",
+ "Unknown filetype" : "Vrsta datoteke nepoznata",
+ "Invalid image" : "Slika neispravna",
+ "An error occurred. Please contact your admin." : "Došlo je do greške. Molimo kontaktirajte vašeg administratora.",
+ "No temporary profile picture available, try again" : "Slike privremenih profila nisu dostupne, pokušajte ponovno",
+ "No crop data provided" : "Nema podataka o rezanju",
+ "No valid crop data provided" : "Nema valjanih podataka za rezanje",
+ "Password reset is disabled" : "Resetiranje lozinke je onemogućeno",
+ "Couldn't reset password because the token is invalid" : "Resetiranje lozinke nije moguće jer je token neispravan.",
+ "Couldn't reset password because the token is expired" : "Resetiranje lozinke nije moguće jer je token istekao",
+ "Could not send reset email because there is no email address for this username. Please contact your administrator." : "Nije moguće poslati poruku za resetiranje e-pošte jer ne postoji adresa e-pošte za ovo korisničko ime. Molimo da kontaktirate vašeg administratora.",
+ "%s password reset" : "%s lozinka resetirana",
+ "Password reset" : "Promjena lozinke",
+ "Click the following button to reset your password. If you have not requested the password reset, then ignore this email." : "Kliknite ovdje kako biste resetirali vašu lozinku. Ako niste dali zahtjev za resetiranje lozinke, ignorirajte ovu poruku.",
+ "Click the following link to reset your password. If you have not requested the password reset, then ignore this email." : "Kliknite ovu poveznicu kako biste resetirali vašu lozinku. Ako niste dali zahtjev za resetiranje lozinke, ignorirajte ovu poruku.",
+ "Reset your password" : "Resetirajte vašu lozinku",
+ "Couldn't send reset email. Please contact your administrator." : "Nije moguće poslati poruku za resetiranje lozinke. Molimo kontaktirajte svog administratora.",
+ "Couldn't send reset email. Please make sure your username is correct." : "Poruku za resetiranje lozinke nije moguće poslati. Molimo provjerite ispravnost svoga korisničkog imena.",
+ "Preparing update" : "Priprema ažuriranja",
+ "Please use the command line updater because automatic updating is disabled in the config.php." : "Molimo da ažurirate putem komandne linije jer je automatsko ažuriranje onemogućeno u config.php.",
+ "Turned on maintenance mode" : "Način rada za održavanje uključen",
+ "Turned off maintenance mode" : "Način rada za održavanje isključen",
+ "Updating database schema" : "Ažuriranje sheme baze podataka",
+ "Updated database" : " Baza podataka ažurirana",
+ "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "U tijeku je provjeranje može li shema baza podataka biti ažurirana (ovo može potrajati ovisno o veličini baze podataka)",
+ "Checked database schema update" : "Provjereno ažuriranje sheme baze podataka",
+ "Checking updates of apps" : "U tijeku je provjeravanje ažuriranja aplikacija",
+ "Update app \"%s\" from appstore" : "Ažurirajte aplikaciju \"%s\" iz trgovine aplikacija",
+ "Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)" : "U tijeku je provjeranje može li shema baza podataka za %s biti ažurirana (ovo može potrajati ovisno o veličini baze podataka)",
+ "Checked database schema update for apps" : "Provjereno ažuriranje sheme baze podataka za aplikacije",
+ "Updated \"%s\" to %s" : "Ažurirano \"%s\" u %s",
+ "Starting code integrity check" : "Provjera integriteta datoteka počinje",
+ "Finished code integrity check" : "Provjera integriteta datoteka završena",
+ "Already up to date" : "Nema potrebe za ažuriranjem",
+ "Search contacts …" : "Pretraži kontakte ...",
+ "Loading your contacts …" : "Učitavanje vaših kontakata ...",
+ "Settings" : "Postavke",
+ "Saving..." : "Spremanje...",
+ "Dismiss" : "Odpusti",
+ "Password" : "Lozinka",
+ "seconds ago" : "prije par sekundi",
+ "The link to reset your password has been sent to your email. If you do not receive it within a reasonable amount of time, check your spam/junk folders.<br>If it is not there ask your local administrator." : "Veza za resetiranje vaše lozinke poslana je na vašu adresu e-pošte. Ako je ne primite unekom razumnom vremenskom roku, provjerite svoje spam/junk mape. <br> Ako nije tamo, kontaktirajtesvoga lokalnog administratora.",
+ "I know what I'm doing" : "Znam što radim",
+ "Password can not be changed. Please contact your administrator." : "Lozinku nije moguće promijeniti. Molimo kontaktirajte svog administratora.",
+ "Reset password" : "Resetirajte lozinku",
+ "No" : "Ne",
+ "Yes" : "Da",
+ "Choose" : "Odaberite",
+ "Error loading file picker template: {error}" : "Pogrešno učitavanje predloška za pronalazača datoteke: {error}",
+ "Error loading message template: {error}" : "Pogrešno učitavanje predloška za poruke: {error}",
+ "read-only" : "samo čitanje",
+ "_{count} file conflict_::_{count} file conflicts_" : ["neželjeno podudaranje u {count} datoteci","neželjeno podudaranje u {count} datoteke","konflikti u {count} datoteke"],
+ "One file conflict" : "Konflikt u jednoj datoteci",
+ "New Files" : "Nove datoteke",
+ "Already existing files" : "Postojeće datoteke",
+ "Which files do you want to keep?" : "Koje datoteke želite zadržati?",
+ "If you select both versions, the copied file will have a number added to its name." : "Ako odaberete obje verzije, kopirana će datoteka uz svoje ime imati i broj.",
+ "Cancel" : "Odustani",
+ "Continue" : "Nastavi",
+ "(all selected)" : "(sve odabrano)",
+ "({count} selected)" : "({count} odabran)",
+ "Error loading file exists template" : "Pogrešno učitavanje predloška DATOTEKA POSTOJI",
+ "Very weak password" : "Lozinka vrlo slaba",
+ "Weak password" : "Lozinka Slaba",
+ "So-so password" : "Lozinka tako-tako",
+ "Good password" : "Lozinka dobra",
+ "Strong password" : "Lozinka snažna",
+ "Error occurred while checking server setup" : "Greška prilikom provjeri postavki servera",
+ "Shared" : "Resurs podijeljen",
+ "Shared with" : "Podijeljeno s...",
+ "Shared by" : "Podijeljeno od...",
+ "Error setting expiration date" : "Pogrešno učitavanje postavke datuma isteka",
+ "The public link will expire no later than {days} days after it is created" : " Javna veza ističe najkasnije {days} dana nakon što je kreirana",
+ "Set expiration date" : "Odredite datum isteka",
+ "Expiration" : "Istjeće",
+ "Expiration date" : "Datum isteka",
+ "Choose a password for the public link" : "Odaberite lozinku za javnu vezu",
+ "Choose a password for the public link or press the \"Enter\" key" : "Odaberite lozinku za javnu vezu ili stisnite \"Enter\" tipku",
+ "Copied!" : "Kopirano!",
+ "Not supported!" : "Nije podržano!",
+ "Press ⌘-C to copy." : "Pritisnite ⌘-C za kopiranje.",
+ "Press Ctrl-C to copy." : "Pritisnite Ctrl-C za kopiranje.",
+ "Resharing is not allowed" : "Ponovno dijeljenje nije dopušteno",
+ "Share to {name}" : "Podijeliti na {name}",
+ "Share link" : "Podijelite vezu",
+ "Link" : "Poveznica",
+ "Password protect" : "Zaštititi lozinkom",
+ "Allow editing" : "Omogući uređivanje",
+ "Email link to person" : "Pošaljite osobi vezu e-poštom",
+ "Send" : "Pošaljite",
+ "Allow upload and editing" : "Omogući učitavanje i uređivanje",
+ "Read only" : "Samo za čitanje",
+ "Shared with you and the group {group} by {owner}" : "Dijeljeno s vama i grupom {group} vlasnika {owner}",
+ "Shared with you by {owner}" : "S vama podijelio {owner}",
+ "group" : "Grupa",
+ "remote" : "na daljinu",
+ "Unshare" : "Prestanite dijeliti",
+ "Can reshare" : "Ponovno dijeljenje omogućeno",
+ "Can edit" : "Uređivanje omogućeno",
+ "Can create" : "Stvaranje omogućeno",
+ "Can delete" : "Brisanje omogućeno",
+ "Error while sharing" : "Pogreška pri dijeljenju",
+ "Share" : "Podijelite",
+ "Name or email address..." : "Ime i adresa e-pošte...",
+ "Name..." : "Ime...",
+ "Error" : "Pogreška",
+ "restricted" : "Ograničeno",
+ "Delete" : "Izbrišite",
+ "Rename" : "Preimenujte",
+ "unknown text" : "nepoznati tekst",
+ "Hello world!" : "Pozdrav svijete!",
+ "sunny" : "sunčano",
+ "Hello {name}, the weather is {weather}" : "Pozdrav {name}, vrijeme je {weather}",
+ "Hello {name}" : "Pozdrav {name}",
+ "_download %n file_::_download %n files_" : ["preuzimanje %n datoteke","preuzimanje %n datoteke","preuzimanje %n datoteka"],
+ "Please reload the page." : "Molimo, ponovno učitajte stranicu",
+ "_The update was successful. Redirecting you to Nextcloud in %n second._::_The update was successful. Redirecting you to Nextcloud in %n seconds._" : ["Ažuriranje uspješno. Preusmjeravanje na Nextcloud za %n sekundu","Ažuriranje uspješno. Preusmjeravanje na Nextcloud za %n sekunde","Ažuriranje uspješno. Preusmjeravanje na Nextcloud za %n sekundi"],
+ "Searching other places" : "Pretraživanje drugih lokacija",
+ "_{count} search result in another folder_::_{count} search results in other folders_" : ["{count} rezultat u drugoj mapi","{count} rezultata u drugoj mapi","{count} rezultata u ostalim mapama"],
+ "Personal" : "Osobno",
+ "Users" : "Korisnici",
+ "Apps" : "Aplikacije",
+ "Admin" : "Admin",
+ "Help" : "Pomoć",
+ "Access forbidden" : "Pristup zabranjen",
+ "File not found" : "Datoteka nije pronađena",
+ "The specified document has not been found on the server." : "Traženi dokument nije pronađen na poslužitelju.",
+ "You can click here to return to %s." : "Kliknite ovdje da se vratite na %s.",
+ "Internal Server Error" : "Pogreška poslužitelja.",
+ "The server was unable to complete your request." : "Poslužitelj nije u mogućnosti izvršiti Vaš zahtjev.",
+ "If this happens again, please send the technical details below to the server administrator." : "U slučaju da se ovo ponovi, molimo da pošaljete tehničke detalje ispod administratoru poslužitelja.",
+ "More details can be found in the server log." : "Više podatake može se naći u logovima na poslužitelju.",
+ "Technical details" : "Tehnički detalji",
+ "Remote Address: %s" : "Udaljena adresa: %s",
+ "Request ID: %s" : "Zahtjev ID: %s",
+ "Code: %s" : "Kod: %s",
+ "Message: %s" : "Poruka: %s",
+ "File: %s" : "Datoteka: %s",
+ "Line: %s" : "Red: %s",
+ "Trace" : "Prati",
+ "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." : "Vašem podatkovnom direktoriju i datotekama vjerojatno se može pristupiti s interneta jer .htaccess datoteka ne radi.",
+ "Create an <strong>admin account</strong>" : "Kreirajte <strong>admin račun</strong>",
+ "Username" : "Korisničko ime",
+ "Storage & database" : "Pohrana & baza podataka",
+ "Data folder" : "Mapa za podatke",
+ "Configure the database" : "Konfigurirajte bazu podataka",
+ "Only %s is available." : "Jedino je %s dostupan.",
+ "Database user" : "Korisnik baze podataka",
+ "Database password" : "Lozinka baze podataka",
+ "Database name" : "Naziv baze podataka",
+ "Database tablespace" : "Tablespace (?) baze podataka",
+ "Database host" : "Glavno računalo baze podataka",
+ "Finish setup" : "Završite postavljanje",
+ "Finishing …" : "Završavanje...",
+ "More apps" : "Više aplikacija",
+ "Search" : "pretraži",
+ "Reset search" : "Resetirajte pretraživanje",
+ "Contacts" : "Kontakti",
+ "Contacts menu" : "Izbornik kontakata",
+ "Settings menu" : "Izbornik postavki",
+ "Confirm your password" : "Potvrdite vašu lozinku",
+ "Server side authentication failed!" : "Autentikacija na strani poslužitelja nije uspjela!",
+ "Please contact your administrator." : "Molimo kontaktirajte svog administratora.",
+ "Please try again or contact your administrator." : "Molimo vas da pokušate ponovno ili da kontaktirate svog administratora.",
+ "Username or email" : "Korisničko ime ili adresa e-pošte",
+ "Log in" : "Prijavite se",
+ "Wrong password." : "Pogrešna lozinka.",
+ "We have detected multiple invalid login attempts from your IP. Therefore your next login is throttled up to 30 seconds." : "Došlo je do nekoliko nevažećih pokušaja prijave sa vaše IP adrese. Vaša iduća prijava je odgođena za maksimalno 30 sekundi.",
+ "Forgot password?" : "Zaboravili Vašu lozinku?",
+ "Back to login" : "Natrag na prijavu",
+ "Connect to your account" : "Povežite se sa svojim računom",
+ "Please log in before granting %s access to your %s account." : "Prijavite se prije nego dopustite %s pristup vašem %s računu.",
+ "App token" : "Token za aplikaciju",
+ "Grant access" : "Dodijeli pristup",
+ "You are about to grant %s access to your %s account." : "Ovim će te dopustiti %s pristup vašem %s računu.",
+ "Redirecting …" : "Preusmjeravanje...",
+ "New password" : "Nova lozinka",
+ "New Password" : "Nova lozinka",
+ "This share is password-protected" : "Ovaj zajednički resurs je zaštićen lozinkom",
+ "The password is wrong. Try again." : "Pogrešna lozinka. Pokušajte ponovno.",
+ "Cancel log in" : "Otkaži prijavu",
+ "Error while validating your second factor" : "Greška prilikom ovažavanja drugog faktora",
+ "Access through untrusted domain" : "Pristup iz nepouzdane domene",
+ "Please contact your administrator. If you are an administrator, edit the \"trusted_domains\" setting in config/config.php like the example in config.sample.php." : "Molimo Vas da kontaktirate vašeg administratora. Ako ste administrator, uredite \"trusted domains\" postavku u config/config.php datoteci po primjeru iz datoteke config.sample.php.",
+ "App update required" : "Ažuriranje aplikacije potrebno",
+ "%s will be updated to version %s" : "%s će biti ažuriran na verziju %s",
+ "These apps will be updated:" : "Slijedeće aplikacije će biti ažurirane:",
+ "These incompatible apps will be disabled:" : "Slijedeće nekompatibilne aplikacije će biti onemogućene:",
+ "The theme %s has been disabled." : "Tema %s je onemogućena",
+ "Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "Prije nego li nastavite, molimo osigurajte da su baza podataka, mapa konfiguracije i mapaza podatke sigurnosno kopirani.",
+ "Start update" : "Započnite ažuriranje",
+ "To avoid timeouts with larger installations, you can instead run the following command from your installation directory:" : "Da biste izbjegli vremensko prekoračenje s većim instalacijama, možete pokrenutisljedeću naredbu iz svoga instalacijskog direktorija:",
+ "Detailed logs" : "Detaljni zapisnik",
+ "Update needed" : "Molimo ažurirajte aplikaciju",
+ "Please use the command line updater because you have a big instance with more than 50 users." : "Molimo da ažurirate putem komandne linije jer imate veliku instancu od preko 50 korisnika.",
+ "Upgrade via web on my own risk" : "Nadogradnja preko mreže na moju vlastitu odgovornost",
+ "This %s instance is currently in maintenance mode, which may take a while." : "Ova %s instanca je trenutno u načinu za održavanje; ovo može potrajati.",
+ "This page will refresh itself when the %s instance is available again." : "Stranica će se sama osvježiti kada %s bude ponovo dostupno.",
+ "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktirajte svog administratora sustava ako se ova poruka ponavlja ili sepojavila neočekivano.",
+ "Thank you for your patience." : "Hvala vam na strpljenju",
+ "There was an error loading your contacts" : "Greška pri učitavanju kontakata",
+ "You are currently running PHP {version}. We encourage you to upgrade your PHP version to take advantage of <a target=\"_blank\" rel=\"noreferrer\" href=\"{phpLink}\">performance and security updates provided by the PHP Group</a> as soon as your distribution supports it." : "Trenutno koristite PHP {version}. Molimo vas da nadogradite vašu PHP verziju da iskoristite <a target=\"_blank\" rel=\"noreferrer\" href=\"{phpLink}\">ažuriranje sigurnosti i performansi od strane PHP grupe</a> čim god vaša distribucija to podržava.",
+ "Some files have not passed the integrity check. Further information on how to resolve this issue can be found in our <a target=\"_blank\" rel=\"noreferrer\" href=\"{docLink}\">documentation</a>. (<a href=\"{codeIntegrityDownloadEndpoint}\">List of invalid files…</a> / <a href=\"{rescanEndpoint}\">Rescan…</a>)" : "Neke datoteke nisu prošle provjeru integriteta. Daljnje informacije o tome kako riješiti ovaj problem se mogu naći u <a target=\"_blank\" rel=\"noreferrer\" href=\"{docLink}\">priloženoj dokumentaciji</a>.(<a href=\"{codeIntegrityDownloadEndpoint}\">Lista nevažećih datoteka...</a>/<a href=\"{rescanEndpoint}\">Ponovo skeniraj...</a>)",
+ "Shared with {recipients}" : "Resurs podijeljen s {recipients}",
+ "Share with other people by entering a user or group or an email address." : "Podijelite sa ostalim korisnicima tako da unesete korisničko ime ili ime grupe ili adresu e-pošte.",
+ "The server encountered an internal error and was unable to complete your request." : "Poslužitelj je naišao na grešku i nije u mogućnosti izvršiti Vaš zahtjev.",
+ "Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report." : "Molimo kontaktirajte svojeg administratora poslužitelja ako se ova greška učestalo pojavljuje, molimo da uključite i tehničke detalje ispod u svojem izvješću.",
+ "For information how to properly configure your server, please see the <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">documentation</a>." : "Za više informacije o tome kako podesiti vaš poslužitelj, molimo da proučite <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">priložene upute</a>.",
+ "This action requires you to confirm your password:" : "Za izvršavanje ove radnje potvrdite vašu lozinku:",
+ "Wrong password. Reset it?" : "Pogrešna lozinka. Promijeniti lozinku?",
+ "Stay logged in" : "Ostanite prijavljeni",
+ "Alternative Logins" : "Alternativne prijave",
+ "You are about to grant \"%s\" access to your %s account." : "Ovim će te dopustiti \"%s\" pristup vašem %s računu.",
+ "Alternative login using app token" : "Alternativna prijava uz pomoću aplikacijskog tokena",
+ "You are accessing the server from an untrusted domain." : "Poslužitelju pristupate iz nepouzdane domene.",
+ "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domains\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Molimo Vas da kontaktirate vašeg administratora. Ako ste administrator ove trenutne instance, uredite \"trusted domains\" postavku u config/config.php datoteci po primjeru iz datoteke config/config.sample.php.",
+ "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Ovisno o vašoj konfiguraciji, kao administrator možete također koristiti gumb dolje da označite domenu kao sigurnu.",
+ "Add \"%s\" as trusted domain" : "Dodajte \"%s\" kao pouzdanu domenu.",
+ "For help, see the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation</a>." : "Za pomoć, molimo vidite <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">priložene upute</a>."
+},
+"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/core/l10n/hr.json b/core/l10n/hr.json
new file mode 100644
index 00000000000..5bb5f76a2ec
--- /dev/null
+++ b/core/l10n/hr.json
@@ -0,0 +1,227 @@
+{ "translations": {
+ "Please select a file." : "Molimo odaberite datoteku.",
+ "File is too big" : "Datoteka je prevelika",
+ "The selected file is not an image." : "Odabrana datoteka nije slika.",
+ "The selected file cannot be read." : "Nije moguće pročitati odabranu datoteku.",
+ "Invalid file provided" : "Nevažeća datoteka",
+ "No image or file provided" : "Nijedna slika ili datoteka nije dobavljena",
+ "Unknown filetype" : "Vrsta datoteke nepoznata",
+ "Invalid image" : "Slika neispravna",
+ "An error occurred. Please contact your admin." : "Došlo je do greške. Molimo kontaktirajte vašeg administratora.",
+ "No temporary profile picture available, try again" : "Slike privremenih profila nisu dostupne, pokušajte ponovno",
+ "No crop data provided" : "Nema podataka o rezanju",
+ "No valid crop data provided" : "Nema valjanih podataka za rezanje",
+ "Password reset is disabled" : "Resetiranje lozinke je onemogućeno",
+ "Couldn't reset password because the token is invalid" : "Resetiranje lozinke nije moguće jer je token neispravan.",
+ "Couldn't reset password because the token is expired" : "Resetiranje lozinke nije moguće jer je token istekao",
+ "Could not send reset email because there is no email address for this username. Please contact your administrator." : "Nije moguće poslati poruku za resetiranje e-pošte jer ne postoji adresa e-pošte za ovo korisničko ime. Molimo da kontaktirate vašeg administratora.",
+ "%s password reset" : "%s lozinka resetirana",
+ "Password reset" : "Promjena lozinke",
+ "Click the following button to reset your password. If you have not requested the password reset, then ignore this email." : "Kliknite ovdje kako biste resetirali vašu lozinku. Ako niste dali zahtjev za resetiranje lozinke, ignorirajte ovu poruku.",
+ "Click the following link to reset your password. If you have not requested the password reset, then ignore this email." : "Kliknite ovu poveznicu kako biste resetirali vašu lozinku. Ako niste dali zahtjev za resetiranje lozinke, ignorirajte ovu poruku.",
+ "Reset your password" : "Resetirajte vašu lozinku",
+ "Couldn't send reset email. Please contact your administrator." : "Nije moguće poslati poruku za resetiranje lozinke. Molimo kontaktirajte svog administratora.",
+ "Couldn't send reset email. Please make sure your username is correct." : "Poruku za resetiranje lozinke nije moguće poslati. Molimo provjerite ispravnost svoga korisničkog imena.",
+ "Preparing update" : "Priprema ažuriranja",
+ "Please use the command line updater because automatic updating is disabled in the config.php." : "Molimo da ažurirate putem komandne linije jer je automatsko ažuriranje onemogućeno u config.php.",
+ "Turned on maintenance mode" : "Način rada za održavanje uključen",
+ "Turned off maintenance mode" : "Način rada za održavanje isključen",
+ "Updating database schema" : "Ažuriranje sheme baze podataka",
+ "Updated database" : " Baza podataka ažurirana",
+ "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "U tijeku je provjeranje može li shema baza podataka biti ažurirana (ovo može potrajati ovisno o veličini baze podataka)",
+ "Checked database schema update" : "Provjereno ažuriranje sheme baze podataka",
+ "Checking updates of apps" : "U tijeku je provjeravanje ažuriranja aplikacija",
+ "Update app \"%s\" from appstore" : "Ažurirajte aplikaciju \"%s\" iz trgovine aplikacija",
+ "Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)" : "U tijeku je provjeranje može li shema baza podataka za %s biti ažurirana (ovo može potrajati ovisno o veličini baze podataka)",
+ "Checked database schema update for apps" : "Provjereno ažuriranje sheme baze podataka za aplikacije",
+ "Updated \"%s\" to %s" : "Ažurirano \"%s\" u %s",
+ "Starting code integrity check" : "Provjera integriteta datoteka počinje",
+ "Finished code integrity check" : "Provjera integriteta datoteka završena",
+ "Already up to date" : "Nema potrebe za ažuriranjem",
+ "Search contacts …" : "Pretraži kontakte ...",
+ "Loading your contacts …" : "Učitavanje vaših kontakata ...",
+ "Settings" : "Postavke",
+ "Saving..." : "Spremanje...",
+ "Dismiss" : "Odpusti",
+ "Password" : "Lozinka",
+ "seconds ago" : "prije par sekundi",
+ "The link to reset your password has been sent to your email. If you do not receive it within a reasonable amount of time, check your spam/junk folders.<br>If it is not there ask your local administrator." : "Veza za resetiranje vaše lozinke poslana je na vašu adresu e-pošte. Ako je ne primite unekom razumnom vremenskom roku, provjerite svoje spam/junk mape. <br> Ako nije tamo, kontaktirajtesvoga lokalnog administratora.",
+ "I know what I'm doing" : "Znam što radim",
+ "Password can not be changed. Please contact your administrator." : "Lozinku nije moguće promijeniti. Molimo kontaktirajte svog administratora.",
+ "Reset password" : "Resetirajte lozinku",
+ "No" : "Ne",
+ "Yes" : "Da",
+ "Choose" : "Odaberite",
+ "Error loading file picker template: {error}" : "Pogrešno učitavanje predloška za pronalazača datoteke: {error}",
+ "Error loading message template: {error}" : "Pogrešno učitavanje predloška za poruke: {error}",
+ "read-only" : "samo čitanje",
+ "_{count} file conflict_::_{count} file conflicts_" : ["neželjeno podudaranje u {count} datoteci","neželjeno podudaranje u {count} datoteke","konflikti u {count} datoteke"],
+ "One file conflict" : "Konflikt u jednoj datoteci",
+ "New Files" : "Nove datoteke",
+ "Already existing files" : "Postojeće datoteke",
+ "Which files do you want to keep?" : "Koje datoteke želite zadržati?",
+ "If you select both versions, the copied file will have a number added to its name." : "Ako odaberete obje verzije, kopirana će datoteka uz svoje ime imati i broj.",
+ "Cancel" : "Odustani",
+ "Continue" : "Nastavi",
+ "(all selected)" : "(sve odabrano)",
+ "({count} selected)" : "({count} odabran)",
+ "Error loading file exists template" : "Pogrešno učitavanje predloška DATOTEKA POSTOJI",
+ "Very weak password" : "Lozinka vrlo slaba",
+ "Weak password" : "Lozinka Slaba",
+ "So-so password" : "Lozinka tako-tako",
+ "Good password" : "Lozinka dobra",
+ "Strong password" : "Lozinka snažna",
+ "Error occurred while checking server setup" : "Greška prilikom provjeri postavki servera",
+ "Shared" : "Resurs podijeljen",
+ "Shared with" : "Podijeljeno s...",
+ "Shared by" : "Podijeljeno od...",
+ "Error setting expiration date" : "Pogrešno učitavanje postavke datuma isteka",
+ "The public link will expire no later than {days} days after it is created" : " Javna veza ističe najkasnije {days} dana nakon što je kreirana",
+ "Set expiration date" : "Odredite datum isteka",
+ "Expiration" : "Istjeće",
+ "Expiration date" : "Datum isteka",
+ "Choose a password for the public link" : "Odaberite lozinku za javnu vezu",
+ "Choose a password for the public link or press the \"Enter\" key" : "Odaberite lozinku za javnu vezu ili stisnite \"Enter\" tipku",
+ "Copied!" : "Kopirano!",
+ "Not supported!" : "Nije podržano!",
+ "Press ⌘-C to copy." : "Pritisnite ⌘-C za kopiranje.",
+ "Press Ctrl-C to copy." : "Pritisnite Ctrl-C za kopiranje.",
+ "Resharing is not allowed" : "Ponovno dijeljenje nije dopušteno",
+ "Share to {name}" : "Podijeliti na {name}",
+ "Share link" : "Podijelite vezu",
+ "Link" : "Poveznica",
+ "Password protect" : "Zaštititi lozinkom",
+ "Allow editing" : "Omogući uređivanje",
+ "Email link to person" : "Pošaljite osobi vezu e-poštom",
+ "Send" : "Pošaljite",
+ "Allow upload and editing" : "Omogući učitavanje i uređivanje",
+ "Read only" : "Samo za čitanje",
+ "Shared with you and the group {group} by {owner}" : "Dijeljeno s vama i grupom {group} vlasnika {owner}",
+ "Shared with you by {owner}" : "S vama podijelio {owner}",
+ "group" : "Grupa",
+ "remote" : "na daljinu",
+ "Unshare" : "Prestanite dijeliti",
+ "Can reshare" : "Ponovno dijeljenje omogućeno",
+ "Can edit" : "Uređivanje omogućeno",
+ "Can create" : "Stvaranje omogućeno",
+ "Can delete" : "Brisanje omogućeno",
+ "Error while sharing" : "Pogreška pri dijeljenju",
+ "Share" : "Podijelite",
+ "Name or email address..." : "Ime i adresa e-pošte...",
+ "Name..." : "Ime...",
+ "Error" : "Pogreška",
+ "restricted" : "Ograničeno",
+ "Delete" : "Izbrišite",
+ "Rename" : "Preimenujte",
+ "unknown text" : "nepoznati tekst",
+ "Hello world!" : "Pozdrav svijete!",
+ "sunny" : "sunčano",
+ "Hello {name}, the weather is {weather}" : "Pozdrav {name}, vrijeme je {weather}",
+ "Hello {name}" : "Pozdrav {name}",
+ "_download %n file_::_download %n files_" : ["preuzimanje %n datoteke","preuzimanje %n datoteke","preuzimanje %n datoteka"],
+ "Please reload the page." : "Molimo, ponovno učitajte stranicu",
+ "_The update was successful. Redirecting you to Nextcloud in %n second._::_The update was successful. Redirecting you to Nextcloud in %n seconds._" : ["Ažuriranje uspješno. Preusmjeravanje na Nextcloud za %n sekundu","Ažuriranje uspješno. Preusmjeravanje na Nextcloud za %n sekunde","Ažuriranje uspješno. Preusmjeravanje na Nextcloud za %n sekundi"],
+ "Searching other places" : "Pretraživanje drugih lokacija",
+ "_{count} search result in another folder_::_{count} search results in other folders_" : ["{count} rezultat u drugoj mapi","{count} rezultata u drugoj mapi","{count} rezultata u ostalim mapama"],
+ "Personal" : "Osobno",
+ "Users" : "Korisnici",
+ "Apps" : "Aplikacije",
+ "Admin" : "Admin",
+ "Help" : "Pomoć",
+ "Access forbidden" : "Pristup zabranjen",
+ "File not found" : "Datoteka nije pronađena",
+ "The specified document has not been found on the server." : "Traženi dokument nije pronađen na poslužitelju.",
+ "You can click here to return to %s." : "Kliknite ovdje da se vratite na %s.",
+ "Internal Server Error" : "Pogreška poslužitelja.",
+ "The server was unable to complete your request." : "Poslužitelj nije u mogućnosti izvršiti Vaš zahtjev.",
+ "If this happens again, please send the technical details below to the server administrator." : "U slučaju da se ovo ponovi, molimo da pošaljete tehničke detalje ispod administratoru poslužitelja.",
+ "More details can be found in the server log." : "Više podatake može se naći u logovima na poslužitelju.",
+ "Technical details" : "Tehnički detalji",
+ "Remote Address: %s" : "Udaljena adresa: %s",
+ "Request ID: %s" : "Zahtjev ID: %s",
+ "Code: %s" : "Kod: %s",
+ "Message: %s" : "Poruka: %s",
+ "File: %s" : "Datoteka: %s",
+ "Line: %s" : "Red: %s",
+ "Trace" : "Prati",
+ "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." : "Vašem podatkovnom direktoriju i datotekama vjerojatno se može pristupiti s interneta jer .htaccess datoteka ne radi.",
+ "Create an <strong>admin account</strong>" : "Kreirajte <strong>admin račun</strong>",
+ "Username" : "Korisničko ime",
+ "Storage & database" : "Pohrana & baza podataka",
+ "Data folder" : "Mapa za podatke",
+ "Configure the database" : "Konfigurirajte bazu podataka",
+ "Only %s is available." : "Jedino je %s dostupan.",
+ "Database user" : "Korisnik baze podataka",
+ "Database password" : "Lozinka baze podataka",
+ "Database name" : "Naziv baze podataka",
+ "Database tablespace" : "Tablespace (?) baze podataka",
+ "Database host" : "Glavno računalo baze podataka",
+ "Finish setup" : "Završite postavljanje",
+ "Finishing …" : "Završavanje...",
+ "More apps" : "Više aplikacija",
+ "Search" : "pretraži",
+ "Reset search" : "Resetirajte pretraživanje",
+ "Contacts" : "Kontakti",
+ "Contacts menu" : "Izbornik kontakata",
+ "Settings menu" : "Izbornik postavki",
+ "Confirm your password" : "Potvrdite vašu lozinku",
+ "Server side authentication failed!" : "Autentikacija na strani poslužitelja nije uspjela!",
+ "Please contact your administrator." : "Molimo kontaktirajte svog administratora.",
+ "Please try again or contact your administrator." : "Molimo vas da pokušate ponovno ili da kontaktirate svog administratora.",
+ "Username or email" : "Korisničko ime ili adresa e-pošte",
+ "Log in" : "Prijavite se",
+ "Wrong password." : "Pogrešna lozinka.",
+ "We have detected multiple invalid login attempts from your IP. Therefore your next login is throttled up to 30 seconds." : "Došlo je do nekoliko nevažećih pokušaja prijave sa vaše IP adrese. Vaša iduća prijava je odgođena za maksimalno 30 sekundi.",
+ "Forgot password?" : "Zaboravili Vašu lozinku?",
+ "Back to login" : "Natrag na prijavu",
+ "Connect to your account" : "Povežite se sa svojim računom",
+ "Please log in before granting %s access to your %s account." : "Prijavite se prije nego dopustite %s pristup vašem %s računu.",
+ "App token" : "Token za aplikaciju",
+ "Grant access" : "Dodijeli pristup",
+ "You are about to grant %s access to your %s account." : "Ovim će te dopustiti %s pristup vašem %s računu.",
+ "Redirecting …" : "Preusmjeravanje...",
+ "New password" : "Nova lozinka",
+ "New Password" : "Nova lozinka",
+ "This share is password-protected" : "Ovaj zajednički resurs je zaštićen lozinkom",
+ "The password is wrong. Try again." : "Pogrešna lozinka. Pokušajte ponovno.",
+ "Cancel log in" : "Otkaži prijavu",
+ "Error while validating your second factor" : "Greška prilikom ovažavanja drugog faktora",
+ "Access through untrusted domain" : "Pristup iz nepouzdane domene",
+ "Please contact your administrator. If you are an administrator, edit the \"trusted_domains\" setting in config/config.php like the example in config.sample.php." : "Molimo Vas da kontaktirate vašeg administratora. Ako ste administrator, uredite \"trusted domains\" postavku u config/config.php datoteci po primjeru iz datoteke config.sample.php.",
+ "App update required" : "Ažuriranje aplikacije potrebno",
+ "%s will be updated to version %s" : "%s će biti ažuriran na verziju %s",
+ "These apps will be updated:" : "Slijedeće aplikacije će biti ažurirane:",
+ "These incompatible apps will be disabled:" : "Slijedeće nekompatibilne aplikacije će biti onemogućene:",
+ "The theme %s has been disabled." : "Tema %s je onemogućena",
+ "Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "Prije nego li nastavite, molimo osigurajte da su baza podataka, mapa konfiguracije i mapaza podatke sigurnosno kopirani.",
+ "Start update" : "Započnite ažuriranje",
+ "To avoid timeouts with larger installations, you can instead run the following command from your installation directory:" : "Da biste izbjegli vremensko prekoračenje s većim instalacijama, možete pokrenutisljedeću naredbu iz svoga instalacijskog direktorija:",
+ "Detailed logs" : "Detaljni zapisnik",
+ "Update needed" : "Molimo ažurirajte aplikaciju",
+ "Please use the command line updater because you have a big instance with more than 50 users." : "Molimo da ažurirate putem komandne linije jer imate veliku instancu od preko 50 korisnika.",
+ "Upgrade via web on my own risk" : "Nadogradnja preko mreže na moju vlastitu odgovornost",
+ "This %s instance is currently in maintenance mode, which may take a while." : "Ova %s instanca je trenutno u načinu za održavanje; ovo može potrajati.",
+ "This page will refresh itself when the %s instance is available again." : "Stranica će se sama osvježiti kada %s bude ponovo dostupno.",
+ "Contact your system administrator if this message persists or appeared unexpectedly." : "Kontaktirajte svog administratora sustava ako se ova poruka ponavlja ili sepojavila neočekivano.",
+ "Thank you for your patience." : "Hvala vam na strpljenju",
+ "There was an error loading your contacts" : "Greška pri učitavanju kontakata",
+ "You are currently running PHP {version}. We encourage you to upgrade your PHP version to take advantage of <a target=\"_blank\" rel=\"noreferrer\" href=\"{phpLink}\">performance and security updates provided by the PHP Group</a> as soon as your distribution supports it." : "Trenutno koristite PHP {version}. Molimo vas da nadogradite vašu PHP verziju da iskoristite <a target=\"_blank\" rel=\"noreferrer\" href=\"{phpLink}\">ažuriranje sigurnosti i performansi od strane PHP grupe</a> čim god vaša distribucija to podržava.",
+ "Some files have not passed the integrity check. Further information on how to resolve this issue can be found in our <a target=\"_blank\" rel=\"noreferrer\" href=\"{docLink}\">documentation</a>. (<a href=\"{codeIntegrityDownloadEndpoint}\">List of invalid files…</a> / <a href=\"{rescanEndpoint}\">Rescan…</a>)" : "Neke datoteke nisu prošle provjeru integriteta. Daljnje informacije o tome kako riješiti ovaj problem se mogu naći u <a target=\"_blank\" rel=\"noreferrer\" href=\"{docLink}\">priloženoj dokumentaciji</a>.(<a href=\"{codeIntegrityDownloadEndpoint}\">Lista nevažećih datoteka...</a>/<a href=\"{rescanEndpoint}\">Ponovo skeniraj...</a>)",
+ "Shared with {recipients}" : "Resurs podijeljen s {recipients}",
+ "Share with other people by entering a user or group or an email address." : "Podijelite sa ostalim korisnicima tako da unesete korisničko ime ili ime grupe ili adresu e-pošte.",
+ "The server encountered an internal error and was unable to complete your request." : "Poslužitelj je naišao na grešku i nije u mogućnosti izvršiti Vaš zahtjev.",
+ "Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report." : "Molimo kontaktirajte svojeg administratora poslužitelja ako se ova greška učestalo pojavljuje, molimo da uključite i tehničke detalje ispod u svojem izvješću.",
+ "For information how to properly configure your server, please see the <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">documentation</a>." : "Za više informacije o tome kako podesiti vaš poslužitelj, molimo da proučite <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">priložene upute</a>.",
+ "This action requires you to confirm your password:" : "Za izvršavanje ove radnje potvrdite vašu lozinku:",
+ "Wrong password. Reset it?" : "Pogrešna lozinka. Promijeniti lozinku?",
+ "Stay logged in" : "Ostanite prijavljeni",
+ "Alternative Logins" : "Alternativne prijave",
+ "You are about to grant \"%s\" access to your %s account." : "Ovim će te dopustiti \"%s\" pristup vašem %s računu.",
+ "Alternative login using app token" : "Alternativna prijava uz pomoću aplikacijskog tokena",
+ "You are accessing the server from an untrusted domain." : "Poslužitelju pristupate iz nepouzdane domene.",
+ "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domains\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Molimo Vas da kontaktirate vašeg administratora. Ako ste administrator ove trenutne instance, uredite \"trusted domains\" postavku u config/config.php datoteci po primjeru iz datoteke config/config.sample.php.",
+ "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Ovisno o vašoj konfiguraciji, kao administrator možete također koristiti gumb dolje da označite domenu kao sigurnu.",
+ "Add \"%s\" as trusted domain" : "Dodajte \"%s\" kao pouzdanu domenu.",
+ "For help, see the <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation</a>." : "Za pomoć, molimo vidite <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">priložene upute</a>."
+},"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/core/l10n/it.js b/core/l10n/it.js
index 69ddd20b542..f097dc8706f 100644
--- a/core/l10n/it.js
+++ b/core/l10n/it.js
@@ -105,6 +105,8 @@ OC.L10N.register(
"Pending" : "In corso",
"Copy to {folder}" : "Copia in {folder}",
"Move to {folder}" : "Sposta in {folder}",
+ "New in" : "Nuovo in",
+ "View changelog" : "Visualizza le novità",
"Very weak password" : "Password molto debole",
"Weak password" : "Password debole",
"So-so password" : "Password così-così",
@@ -174,6 +176,7 @@ OC.L10N.register(
"Read only" : "Sola lettura",
"File drop (upload only)" : "Rilascia file (solo caricamento)",
"Shared with you and the group {group} by {owner}" : "Condiviso con te e con il gruppo {group} da {owner}",
+ "Shared with you and {circle} by {owner}" : "Condiviso con te e {circle} da {owner}",
"Shared with you by {owner}" : "Condiviso con te da {owner}",
"Choose a password for the mail share" : "Scegli una password per la condivisione tramite posta",
"{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha condiviso tramite collegamento",
diff --git a/core/l10n/it.json b/core/l10n/it.json
index 32c99388d23..a68389dbf1a 100644
--- a/core/l10n/it.json
+++ b/core/l10n/it.json
@@ -103,6 +103,8 @@
"Pending" : "In corso",
"Copy to {folder}" : "Copia in {folder}",
"Move to {folder}" : "Sposta in {folder}",
+ "New in" : "Nuovo in",
+ "View changelog" : "Visualizza le novità",
"Very weak password" : "Password molto debole",
"Weak password" : "Password debole",
"So-so password" : "Password così-così",
@@ -172,6 +174,7 @@
"Read only" : "Sola lettura",
"File drop (upload only)" : "Rilascia file (solo caricamento)",
"Shared with you and the group {group} by {owner}" : "Condiviso con te e con il gruppo {group} da {owner}",
+ "Shared with you and {circle} by {owner}" : "Condiviso con te e {circle} da {owner}",
"Shared with you by {owner}" : "Condiviso con te da {owner}",
"Choose a password for the mail share" : "Scegli una password per la condivisione tramite posta",
"{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatorDisplayName}} ha condiviso tramite collegamento",
diff --git a/core/l10n/pt_BR.js b/core/l10n/pt_BR.js
index 8a1ac7ce6ca..8e9b92de8a3 100644
--- a/core/l10n/pt_BR.js
+++ b/core/l10n/pt_BR.js
@@ -105,6 +105,8 @@ OC.L10N.register(
"Pending" : "Pendente",
"Copy to {folder}" : "Copiar para {folder}",
"Move to {folder}" : "Mover para {folder}",
+ "New in" : "Novo em",
+ "View changelog" : "Ver alterações",
"Very weak password" : "Senha muito fraca",
"Weak password" : "Senha fraca",
"So-so password" : "Senha mais ou menos",
@@ -174,6 +176,7 @@ OC.L10N.register(
"Read only" : "Somente leitura",
"File drop (upload only)" : "Zona de arquivos (somente envio)",
"Shared with you and the group {group} by {owner}" : "Compartilhado com você e com o grupo {group} por {owner}",
+ "Shared with you and {circle} by {owner}" : "Compartilhado com você e {circle} por {owner}",
"Shared with you by {owner}" : "Compartilhado com você por {owner}",
"Choose a password for the mail share" : "Escolha uma senha para o compartilhamento de e-mail",
"{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatiorDisplayName}} compartilhou via link",
@@ -275,7 +278,7 @@ OC.L10N.register(
"Database name" : "Nome do banco de dados",
"Database tablespace" : "Espaço de tabela do banco de dados",
"Database host" : "Host do banco de dados",
- "Please specify the port number along with the host name (e.g., localhost:5432)." : "Por favor especifique o nome do host e o número de porto  (ex., localhost:5432).",
+ "Please specify the port number along with the host name (e.g., localhost:5432)." : "Por favor especifique o nome do host e porta (ex., localhost:5432).",
"Performance warning" : "Alerta de performance",
"SQLite will be used as database." : "SQLite será usado como banco de dados",
"For larger installations we recommend to choose a different database backend." : "Para instalações maiores é recomendável escolher uma plataforma de serviço de banco de dados diferente.",
diff --git a/core/l10n/pt_BR.json b/core/l10n/pt_BR.json
index 2b26eceb8ac..d27bb821b7c 100644
--- a/core/l10n/pt_BR.json
+++ b/core/l10n/pt_BR.json
@@ -103,6 +103,8 @@
"Pending" : "Pendente",
"Copy to {folder}" : "Copiar para {folder}",
"Move to {folder}" : "Mover para {folder}",
+ "New in" : "Novo em",
+ "View changelog" : "Ver alterações",
"Very weak password" : "Senha muito fraca",
"Weak password" : "Senha fraca",
"So-so password" : "Senha mais ou menos",
@@ -172,6 +174,7 @@
"Read only" : "Somente leitura",
"File drop (upload only)" : "Zona de arquivos (somente envio)",
"Shared with you and the group {group} by {owner}" : "Compartilhado com você e com o grupo {group} por {owner}",
+ "Shared with you and {circle} by {owner}" : "Compartilhado com você e {circle} por {owner}",
"Shared with you by {owner}" : "Compartilhado com você por {owner}",
"Choose a password for the mail share" : "Escolha uma senha para o compartilhamento de e-mail",
"{{shareInitiatorDisplayName}} shared via link" : "{{shareInitiatiorDisplayName}} compartilhou via link",
@@ -273,7 +276,7 @@
"Database name" : "Nome do banco de dados",
"Database tablespace" : "Espaço de tabela do banco de dados",
"Database host" : "Host do banco de dados",
- "Please specify the port number along with the host name (e.g., localhost:5432)." : "Por favor especifique o nome do host e o número de porto  (ex., localhost:5432).",
+ "Please specify the port number along with the host name (e.g., localhost:5432)." : "Por favor especifique o nome do host e porta (ex., localhost:5432).",
"Performance warning" : "Alerta de performance",
"SQLite will be used as database." : "SQLite será usado como banco de dados",
"For larger installations we recommend to choose a different database backend." : "Para instalações maiores é recomendável escolher uma plataforma de serviço de banco de dados diferente.",
diff --git a/core/routes.php b/core/routes.php
index 90282c5ebf7..c5df3a362f5 100644
--- a/core/routes.php
+++ b/core/routes.php
@@ -76,6 +76,8 @@ $application->registerRoutes($this, [
['root' => '/core', 'name' => 'Navigation#getAppsNavigation', 'url' => '/navigation/apps', 'verb' => 'GET'],
['root' => '/core', 'name' => 'Navigation#getSettingsNavigation', 'url' => '/navigation/settings', 'verb' => 'GET'],
['root' => '/core', 'name' => 'AutoComplete#get', 'url' => '/autocomplete/get', 'verb' => 'GET'],
+ ['root' => '/core', 'name' => 'WhatsNew#get', 'url' => '/whatsnew', 'verb' => 'GET'],
+ ['root' => '/core', 'name' => 'WhatsNew#dismiss', 'url' => '/whatsnew', 'verb' => 'POST'],
],
]);
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 7113f60bc68..1c67fb9327f 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -259,6 +259,7 @@ return array(
'OCP\\IUserSession' => $baseDir . '/lib/public/IUserSession.php',
'OCP\\Image' => $baseDir . '/lib/public/Image.php',
'OCP\\L10N\\IFactory' => $baseDir . '/lib/public/L10N/IFactory.php',
+ 'OCP\\L10N\\ILanguageIterator' => $baseDir . '/lib/public/L10N/ILanguageIterator.php',
'OCP\\LDAP\\IDeletionFlagSupport' => $baseDir . '/lib/public/LDAP/IDeletionFlagSupport.php',
'OCP\\LDAP\\ILDAPProvider' => $baseDir . '/lib/public/LDAP/ILDAPProvider.php',
'OCP\\LDAP\\ILDAPProviderFactory' => $baseDir . '/lib/public/LDAP/ILDAPProviderFactory.php',
@@ -596,6 +597,7 @@ return array(
'OC\\Core\\Controller\\TwoFactorChallengeController' => $baseDir . '/core/Controller/TwoFactorChallengeController.php',
'OC\\Core\\Controller\\UserController' => $baseDir . '/core/Controller/UserController.php',
'OC\\Core\\Controller\\WalledGardenController' => $baseDir . '/core/Controller/WalledGardenController.php',
+ 'OC\\Core\\Controller\\WhatsNewController' => $baseDir . '/core/Controller/WhatsNewController.php',
'OC\\Core\\Middleware\\TwoFactorMiddleware' => $baseDir . '/core/Middleware/TwoFactorMiddleware.php',
'OC\\Core\\Migrations\\Version13000Date20170705121758' => $baseDir . '/core/Migrations/Version13000Date20170705121758.php',
'OC\\Core\\Migrations\\Version13000Date20170718121200' => $baseDir . '/core/Migrations/Version13000Date20170718121200.php',
@@ -793,6 +795,7 @@ return array(
'OC\\L10N\\Factory' => $baseDir . '/lib/private/L10N/Factory.php',
'OC\\L10N\\L10N' => $baseDir . '/lib/private/L10N/L10N.php',
'OC\\L10N\\L10NString' => $baseDir . '/lib/private/L10N/L10NString.php',
+ 'OC\\L10N\\LanguageIterator' => $baseDir . '/lib/private/L10N/LanguageIterator.php',
'OC\\L10N\\LanguageNotFoundException' => $baseDir . '/lib/private/L10N/LanguageNotFoundException.php',
'OC\\LargeFileHelper' => $baseDir . '/lib/private/LargeFileHelper.php',
'OC\\Lock\\AbstractLockingProvider' => $baseDir . '/lib/private/Lock/AbstractLockingProvider.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index ffb50df5b09..e40a5ea75db 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -289,6 +289,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\IUserSession' => __DIR__ . '/../../..' . '/lib/public/IUserSession.php',
'OCP\\Image' => __DIR__ . '/../../..' . '/lib/public/Image.php',
'OCP\\L10N\\IFactory' => __DIR__ . '/../../..' . '/lib/public/L10N/IFactory.php',
+ 'OCP\\L10N\\ILanguageIterator' => __DIR__ . '/../../..' . '/lib/public/L10N/ILanguageIterator.php',
'OCP\\LDAP\\IDeletionFlagSupport' => __DIR__ . '/../../..' . '/lib/public/LDAP/IDeletionFlagSupport.php',
'OCP\\LDAP\\ILDAPProvider' => __DIR__ . '/../../..' . '/lib/public/LDAP/ILDAPProvider.php',
'OCP\\LDAP\\ILDAPProviderFactory' => __DIR__ . '/../../..' . '/lib/public/LDAP/ILDAPProviderFactory.php',
@@ -626,6 +627,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Core\\Controller\\TwoFactorChallengeController' => __DIR__ . '/../../..' . '/core/Controller/TwoFactorChallengeController.php',
'OC\\Core\\Controller\\UserController' => __DIR__ . '/../../..' . '/core/Controller/UserController.php',
'OC\\Core\\Controller\\WalledGardenController' => __DIR__ . '/../../..' . '/core/Controller/WalledGardenController.php',
+ 'OC\\Core\\Controller\\WhatsNewController' => __DIR__ . '/../../..' . '/core/Controller/WhatsNewController.php',
'OC\\Core\\Middleware\\TwoFactorMiddleware' => __DIR__ . '/../../..' . '/core/Middleware/TwoFactorMiddleware.php',
'OC\\Core\\Migrations\\Version13000Date20170705121758' => __DIR__ . '/../../..' . '/core/Migrations/Version13000Date20170705121758.php',
'OC\\Core\\Migrations\\Version13000Date20170718121200' => __DIR__ . '/../../..' . '/core/Migrations/Version13000Date20170718121200.php',
@@ -823,6 +825,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\L10N\\Factory' => __DIR__ . '/../../..' . '/lib/private/L10N/Factory.php',
'OC\\L10N\\L10N' => __DIR__ . '/../../..' . '/lib/private/L10N/L10N.php',
'OC\\L10N\\L10NString' => __DIR__ . '/../../..' . '/lib/private/L10N/L10NString.php',
+ 'OC\\L10N\\LanguageIterator' => __DIR__ . '/../../..' . '/lib/private/L10N/LanguageIterator.php',
'OC\\L10N\\LanguageNotFoundException' => __DIR__ . '/../../..' . '/lib/private/L10N/LanguageNotFoundException.php',
'OC\\LargeFileHelper' => __DIR__ . '/../../..' . '/lib/private/LargeFileHelper.php',
'OC\\Lock\\AbstractLockingProvider' => __DIR__ . '/../../..' . '/lib/private/Lock/AbstractLockingProvider.php',
diff --git a/lib/l10n/de.js b/lib/l10n/de.js
index 89423e706bb..9aab5f4ad70 100644
--- a/lib/l10n/de.js
+++ b/lib/l10n/de.js
@@ -228,6 +228,11 @@ OC.L10N.register(
"Check the value of \"datadirectory\" in your configuration" : "Überprüfe bitte die Angabe unter „datadirectory“ in Deiner Konfiguration",
"Your data directory is invalid" : "Dein Datenverzeichnis ist ungültig",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Stelle sicher, dass eine Datei \".ocdata\" im Wurzelverzeichnis des data-Verzeichnisses existiert.",
+ "Action \"%s\" not supported or implemented." : "Aktion \"%s\" wird nicht unterstützt oder ist nicht implementiert.",
+ "Authentication failed, wrong token or provider ID given" : "Authentifizierung ist fehlgeschlagen. Falsches Token oder Provider-ID wurde übertragen.",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Es fehlen Parameter um die Anfrage zu bearbeiten. Fehlende Parameter: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "ID \"%s\" wird bereits von Cloud-Federation-Provider \"%s\" verwendet",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud-Federation-Provider mit ID: \"%s\" ist nicht vorhanden.",
"Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf „%s“ konnte nicht ermittelt werden.",
"Storage unauthorized. %s" : "Speicher nicht authorisiert. %s",
"Storage incomplete configuration. %s" : "Speicher-Konfiguration unvollständig. %s",
diff --git a/lib/l10n/de.json b/lib/l10n/de.json
index a0cdf424c68..9b2858d2a8c 100644
--- a/lib/l10n/de.json
+++ b/lib/l10n/de.json
@@ -226,6 +226,11 @@
"Check the value of \"datadirectory\" in your configuration" : "Überprüfe bitte die Angabe unter „datadirectory“ in Deiner Konfiguration",
"Your data directory is invalid" : "Dein Datenverzeichnis ist ungültig",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Stelle sicher, dass eine Datei \".ocdata\" im Wurzelverzeichnis des data-Verzeichnisses existiert.",
+ "Action \"%s\" not supported or implemented." : "Aktion \"%s\" wird nicht unterstützt oder ist nicht implementiert.",
+ "Authentication failed, wrong token or provider ID given" : "Authentifizierung ist fehlgeschlagen. Falsches Token oder Provider-ID wurde übertragen.",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Es fehlen Parameter um die Anfrage zu bearbeiten. Fehlende Parameter: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "ID \"%s\" wird bereits von Cloud-Federation-Provider \"%s\" verwendet",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud-Federation-Provider mit ID: \"%s\" ist nicht vorhanden.",
"Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf „%s“ konnte nicht ermittelt werden.",
"Storage unauthorized. %s" : "Speicher nicht authorisiert. %s",
"Storage incomplete configuration. %s" : "Speicher-Konfiguration unvollständig. %s",
diff --git a/lib/l10n/de_DE.js b/lib/l10n/de_DE.js
index b1fb6f1a21e..35914a3da10 100644
--- a/lib/l10n/de_DE.js
+++ b/lib/l10n/de_DE.js
@@ -228,6 +228,11 @@ OC.L10N.register(
"Check the value of \"datadirectory\" in your configuration" : "Überprüfen Sie bitte die Angabe unter „datadirectory“ in Ihrer Konfiguration",
"Your data directory is invalid" : "Dein Datenverzeichnis ist ungültig.",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Stellen Sie sicher, dass eine Datei \".ocdata\" im Wurzelverzeichnis des data-Verzeichnisses existiert.",
+ "Action \"%s\" not supported or implemented." : "Aktion \"%s\" wird nicht unterstützt oder ist nicht implementiert.",
+ "Authentication failed, wrong token or provider ID given" : "Authentifizierung ist fehlgeschlagen. Falsches Token oder Provider-ID wurde übertragen.",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Es fehlen Parameter um die Anfrage zu bearbeiten. Fehlende Parameter: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "ID \"%s\" wird bereits von Cloud-Federation-Provider \"%s\" verwendet.",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud-Federation-Provider mit ID: \"%s\" ist nicht vorhanden.",
"Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf „%s“ konnte nicht ermittelt werden.",
"Storage unauthorized. %s" : "Speicher nicht authorisiert. %s",
"Storage incomplete configuration. %s" : "Speicher-Konfiguration unvollständig. %s",
diff --git a/lib/l10n/de_DE.json b/lib/l10n/de_DE.json
index cd5471619f3..95fedd309f3 100644
--- a/lib/l10n/de_DE.json
+++ b/lib/l10n/de_DE.json
@@ -226,6 +226,11 @@
"Check the value of \"datadirectory\" in your configuration" : "Überprüfen Sie bitte die Angabe unter „datadirectory“ in Ihrer Konfiguration",
"Your data directory is invalid" : "Dein Datenverzeichnis ist ungültig.",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Stellen Sie sicher, dass eine Datei \".ocdata\" im Wurzelverzeichnis des data-Verzeichnisses existiert.",
+ "Action \"%s\" not supported or implemented." : "Aktion \"%s\" wird nicht unterstützt oder ist nicht implementiert.",
+ "Authentication failed, wrong token or provider ID given" : "Authentifizierung ist fehlgeschlagen. Falsches Token oder Provider-ID wurde übertragen.",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Es fehlen Parameter um die Anfrage zu bearbeiten. Fehlende Parameter: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "ID \"%s\" wird bereits von Cloud-Federation-Provider \"%s\" verwendet.",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud-Federation-Provider mit ID: \"%s\" ist nicht vorhanden.",
"Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf „%s“ konnte nicht ermittelt werden.",
"Storage unauthorized. %s" : "Speicher nicht authorisiert. %s",
"Storage incomplete configuration. %s" : "Speicher-Konfiguration unvollständig. %s",
diff --git a/lib/private/DB/MySqlTools.php b/lib/private/DB/MySqlTools.php
index 7f0ba473268..b67aaffe5b4 100644
--- a/lib/private/DB/MySqlTools.php
+++ b/lib/private/DB/MySqlTools.php
@@ -34,17 +34,36 @@ class MySqlTools {
* @return bool
*/
public function supports4ByteCharset(IDBConnection $connection) {
- foreach (['innodb_file_format' => 'Barracuda', 'innodb_large_prefix' => 'ON', 'innodb_file_per_table' => 'ON'] as $var => $val) {
+ $variables = ['innodb_file_per_table' => 'ON'];
+ if (!$this->isMariaDBWithLargePrefix($connection)) {
+ $variables['innodb_file_format'] = 'Barracuda';
+ $variables['innodb_large_prefix'] = 'ON';
+ }
+
+ foreach ($variables as $var => $val) {
$result = $connection->executeQuery("SHOW VARIABLES LIKE '$var'");
- $rows = $result->fetch();
+ $row = $result->fetch();
$result->closeCursor();
- if ($rows === false) {
+ if ($row === false) {
return false;
}
- if (strcasecmp($rows['Value'], $val) !== 0) {
+ if (strcasecmp($row['Value'], $val) !== 0) {
return false;
}
}
return true;
}
+
+ protected function isMariaDBWithLargePrefix(IDBConnection $connection) {
+ $result = $connection->executeQuery('SELECT VERSION()');
+ $row = strtolower($result->fetchColumn());
+ $result->closeCursor();
+
+ if ($row === false) {
+ return false;
+ }
+
+ return strpos($row, 'maria') && version_compare($row, '10.3', '>=') ||
+ strpos($row, 'maria') === false && version_compare($row, '8.0', '>=');
+ }
}
diff --git a/lib/private/L10N/Factory.php b/lib/private/L10N/Factory.php
index 79495f5ff88..cc2de174509 100644
--- a/lib/private/L10N/Factory.php
+++ b/lib/private/L10N/Factory.php
@@ -35,6 +35,7 @@ use OCP\IRequest;
use OCP\IUser;
use OCP\IUserSession;
use OCP\L10N\IFactory;
+use OCP\L10N\ILanguageIterator;
/**
* A factory that generates language instances
@@ -322,35 +323,12 @@ class Factory implements IFactory {
return array_search($lang, $languages) !== false;
}
- public function iterateLanguage(bool $reset = false): string {
- static $i = 0;
- if($reset) {
- $i = 0;
- }
- switch($i) {
- /** @noinspection PhpMissingBreakStatementInspection */
- case 0:
- $i++;
- $forcedLang = $this->config->getSystemValue('force_language', false);
- if(is_string($forcedLang)) {
- return $forcedLang;
- }
- /** @noinspection PhpMissingBreakStatementInspection */
- case 1:
- $i++;
- $user = $this->userSession->getUser();
- if($user instanceof IUser) {
- $userLang = $this->config->getUserValue($user->getUID(), 'core', 'lang', null);
- if(is_string($userLang)) {
- return $userLang;
- }
- }
- case 2:
- $i++;
- return $this->config->getSystemValue('default_language', 'en');
- default:
- return 'en';
+ public function getLanguageIterator(IUser $user = null): ILanguageIterator {
+ $user = $user ?? $this->userSession->getUser();
+ if($user === null) {
+ throw new \RuntimeException('Failed to get an IUser instance');
}
+ return new LanguageIterator($user, $this->config);
}
/**
diff --git a/lib/private/L10N/LanguageIterator.php b/lib/private/L10N/LanguageIterator.php
new file mode 100644
index 00000000000..ba8f942c912
--- /dev/null
+++ b/lib/private/L10N/LanguageIterator.php
@@ -0,0 +1,137 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.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 OC\L10N;
+
+use OCP\IConfig;
+use OCP\IUser;
+use OCP\L10N\ILanguageIterator;
+
+class LanguageIterator implements ILanguageIterator {
+ private $i = 0;
+ /** @var IConfig */
+ private $config;
+ /** @var IUser */
+ private $user;
+
+ public function __construct(IUser $user, IConfig $config) {
+ $this->config = $config;
+ $this->user = $user;
+ }
+
+ /**
+ * Rewind the Iterator to the first element
+ */
+ public function rewind() {
+ $this->i = 0;
+ }
+
+ /**
+ * Return the current element
+ *
+ * @since 14.0.0
+ */
+ public function current(): string {
+ switch($this->i) {
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case 0:
+ $forcedLang = $this->config->getSystemValue('force_language', false);
+ if(is_string($forcedLang)) {
+ return $forcedLang;
+ }
+ $this->next();
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case 1:
+ $forcedLang = $this->config->getSystemValue('force_language', false);
+ if(is_string($forcedLang)
+ && ($truncated = $this->getTruncatedLanguage($forcedLang)) !== $forcedLang
+ ) {
+ return $truncated;
+ }
+ $this->next();
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case 2:
+ $userLang = $this->config->getUserValue($this->user->getUID(), 'core', 'lang', null);
+ if(is_string($userLang)) {
+ return $userLang;
+ }
+ $this->next();
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case 3:
+ $userLang = $this->config->getUserValue($this->user->getUID(), 'core', 'lang', null);
+ if(is_string($userLang)
+ && ($truncated = $this->getTruncatedLanguage($userLang)) !== $userLang
+ ) {
+ return $truncated;
+ }
+ $this->next();
+ case 4:
+ return $this->config->getSystemValue('default_language', 'en');
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case 5:
+ $defaultLang = $this->config->getSystemValue('default_language', 'en');
+ if(($truncated = $this->getTruncatedLanguage($defaultLang)) !== $defaultLang) {
+ return $truncated;
+ }
+ $this->next();
+ default:
+ return 'en';
+ }
+ }
+
+ /**
+ * Move forward to next element
+ *
+ * @since 14.0.0
+ */
+ public function next() {
+ ++$this->i;
+ }
+
+ /**
+ * Return the key of the current element
+ *
+ * @since 14.0.0
+ */
+ public function key(): int {
+ return $this->i;
+ }
+
+ /**
+ * Checks if current position is valid
+ *
+ * @since 14.0.0
+ */
+ public function valid(): bool {
+ return $this->i <= 6;
+ }
+
+ protected function getTruncatedLanguage(string $lang):string {
+ $pos = strpos($lang, '_');
+ if($pos !== false) {
+ $lang = substr($lang, 0, $pos);
+ }
+ return $lang;
+ }
+}
diff --git a/lib/private/Preview/Office.php b/lib/private/Preview/Office.php
index 955ab249df2..4a2aa7f4953 100644
--- a/lib/private/Preview/Office.php
+++ b/lib/private/Preview/Office.php
@@ -43,24 +43,24 @@ abstract class Office extends Provider {
$tmpDir = \OC::$server->getTempManager()->getTempBaseDir();
- $defaultParameters = ' -env:UserInstallation=file://' . escapeshellarg($tmpDir . '/owncloud-' . \OC_Util::getInstanceId() . '/') . ' --headless --nologo --nofirststartwizard --invisible --norestore --convert-to pdf --outdir ';
+ $defaultParameters = ' -env:UserInstallation=file://' . escapeshellarg($tmpDir . '/owncloud-' . \OC_Util::getInstanceId() . '/') . ' --headless --nologo --nofirststartwizard --invisible --norestore --convert-to png --outdir ';
$clParameters = \OC::$server->getConfig()->getSystemValue('preview_office_cl_parameters', $defaultParameters);
$exec = $this->cmd . $clParameters . escapeshellarg($tmpDir) . ' ' . escapeshellarg($absPath);
shell_exec($exec);
- //create imagick object from pdf
- $pdfPreview = null;
+ //create imagick object from png
+ $pngPreview = null;
try {
list($dirname, , , $filename) = array_values(pathinfo($absPath));
- $pdfPreview = $dirname . '/' . $filename . '.pdf';
+ $pngPreview = $dirname . '/' . $filename . '.png';
- $pdf = new \imagick($pdfPreview . '[0]');
- $pdf->setImageFormat('jpg');
+ $png = new \imagick($pngPreview . '[0]');
+ $png->setImageFormat('jpg');
} catch (\Exception $e) {
unlink($absPath);
- unlink($pdfPreview);
+ unlink($pngPreview);
\OC::$server->getLogger()->logException($e, [
'level' => ILogger::ERROR,
'app' => 'core',
@@ -69,10 +69,10 @@ abstract class Office extends Provider {
}
$image = new \OC_Image();
- $image->loadFromData($pdf);
+ $image->loadFromData($png);
unlink($absPath);
- unlink($pdfPreview);
+ unlink($pngPreview);
if ($image->valid()) {
$image->scaleDownToFit($maxX, $maxY);
diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php
index 80ef9412ffa..e4d34146911 100644
--- a/lib/private/Share20/ProviderFactory.php
+++ b/lib/private/Share20/ProviderFactory.php
@@ -251,7 +251,7 @@ class ProviderFactory implements IProviderFactory {
$shareType === \OCP\Share::SHARE_TYPE_LINK
) {
$provider = $this->defaultShareProvider();
- } else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE || \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
+ } else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE || $shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
$provider = $this->federatedShareProvider();
} else if ($shareType === \OCP\Share::SHARE_TYPE_EMAIL) {
$provider = $this->getShareByMailProvider();
diff --git a/lib/private/Share20/Share.php b/lib/private/Share20/Share.php
index 1836d6708c5..d7810165dac 100644
--- a/lib/private/Share20/Share.php
+++ b/lib/private/Share20/Share.php
@@ -48,6 +48,10 @@ class Share implements \OCP\Share\IShare {
/** @var string */
private $sharedWith;
/** @var string */
+ private $sharedWithDisplayName;
+ /** @var string */
+ private $sharedWithAvatar;
+ /** @var string */
private $sharedBy;
/** @var string */
private $shareOwner;
@@ -254,6 +258,42 @@ class Share implements \OCP\Share\IShare {
/**
* @inheritdoc
*/
+ public function setSharedWithDisplayName($displayName) {
+ if (!is_string($displayName)) {
+ throw new \InvalidArgumentException();
+ }
+ $this->sharedWithDisplayName = $displayName;
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getSharedWithDisplayName() {
+ return $this->sharedWithDisplayName;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setSharedWithAvatar($src) {
+ if (!is_string($src)) {
+ throw new \InvalidArgumentException();
+ }
+ $this->sharedWithAvatar = $src;
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getSharedWithAvatar() {
+ return $this->sharedWithAvatar;
+ }
+
+ /**
+ * @inheritdoc
+ */
public function setPermissions($permissions) {
//TODO checkes
diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php
index 5e6719593a3..1efdf8b441c 100644
--- a/lib/private/TemplateLayout.php
+++ b/lib/private/TemplateLayout.php
@@ -122,6 +122,7 @@ class TemplateLayout extends \OC_Template {
$this->assign('bodyid', 'body-login');
} else if ($renderAs == 'guest') {
parent::__construct('core', 'layout.guest');
+ \OC_Util::addStyle('guest');
$this->assign('bodyid', 'body-login');
} else if ($renderAs == 'public') {
parent::__construct('core', 'layout.public');
@@ -187,7 +188,7 @@ class TemplateLayout extends \OC_Template {
&& !\OCP\Util::needUpgrade()
&& $pathInfo !== ''
&& !preg_match('/^\/login/', $pathInfo)
- && $renderAs !== 'error' && $renderAs !== 'guest'
+ && $renderAs !== 'error'
) {
$cssFiles = self::findStylesheetFiles(\OC_Util::$styles);
} else {
diff --git a/lib/private/Updater/ChangesCheck.php b/lib/private/Updater/ChangesCheck.php
index 095f63db879..095cf396e89 100644
--- a/lib/private/Updater/ChangesCheck.php
+++ b/lib/private/Updater/ChangesCheck.php
@@ -48,6 +48,15 @@ class ChangesCheck {
}
/**
+ * @throws DoesNotExistException
+ */
+ public function getChangesForVersion(string $version): array {
+ $version = $this->normalizeVersion($version);
+ $changesInfo = $this->mapper->getChanges($version);
+ return json_decode($changesInfo->getData(), true);
+ }
+
+ /**
* @throws \Exception
*/
public function check(string $uri, string $version): array {
@@ -145,7 +154,7 @@ class ChangesCheck {
* returns a x.y.z form of the provided version. Extra numbers will be
* omitted, missing ones added as zeros.
*/
- protected function normalizeVersion(string $version): string {
+ public function normalizeVersion(string $version): string {
$versionNumbers = array_slice(explode('.', $version), 0, 3);
$versionNumbers[0] = $versionNumbers[0] ?: '0'; // deal with empty input
while(count($versionNumbers) < 3) {
diff --git a/lib/public/L10N/IFactory.php b/lib/public/L10N/IFactory.php
index 9c006073200..1bc231e4e2e 100644
--- a/lib/public/L10N/IFactory.php
+++ b/lib/public/L10N/IFactory.php
@@ -21,6 +21,8 @@
*/
namespace OCP\L10N;
+use OCP\IUser;
+
/**
* @since 8.2.0
*/
@@ -93,10 +95,16 @@ interface IFactory {
/**
* iterate through language settings (if provided) in this order:
* 1. returns the forced language or:
- * 2. returns the user language or:
- * 3. returns the system default language or:
- * 4+∞. returns 'en'
+ * 2. if applicable, the trunk of 1 (e.g. "fu" instead of "fu_BAR"
+ * 3. returns the user language or:
+ * 4. if applicable, the trunk of 3
+ * 5. returns the system default language or:
+ * 6. if applicable, the trunk of 5
+ * 7+∞. returns 'en'
+ *
+ * Hint: in most cases findLanguage() suits you fine
+ *
* @since 14.0.0
*/
- public function iterateLanguage(bool $reset = false): string;
+ public function getLanguageIterator(IUser $user = null): ILanguageIterator;
}
diff --git a/lib/public/L10N/ILanguageIterator.php b/lib/public/L10N/ILanguageIterator.php
new file mode 100644
index 00000000000..ef923dfd249
--- /dev/null
+++ b/lib/public/L10N/ILanguageIterator.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.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 OCP\L10N;
+
+/**
+ * Interface ILanguageIterator
+ *
+ * iterator across language settings (if provided) in this order:
+ * 1. returns the forced language or:
+ * 2. if applicable, the trunk of 1 (e.g. "fu" instead of "fu_BAR"
+ * 3. returns the user language or:
+ * 4. if applicable, the trunk of 3
+ * 5. returns the system default language or:
+ * 6. if applicable, the trunk of 5
+ * 7+∞. returns 'en'
+ *
+ * if settings are not present or truncating is not applicable, the iterator
+ * skips to the next valid item itself
+ *
+ * @package OCP\L10N
+ *
+ * @since 14.0.0
+ */
+interface ILanguageIterator extends \Iterator {
+
+ /**
+ * Return the current element
+ *
+ * @since 14.0.0
+ */
+ public function current(): string;
+
+ /**
+ * Move forward to next element
+ *
+ * @since 14.0.0
+ */
+ public function next();
+
+ /**
+ * Return the key of the current element
+ *
+ * @since 14.0.0
+ */
+ public function key():int;
+
+ /**
+ * Checks if current position is valid
+ *
+ * @since 14.0.0
+ */
+ public function valid():bool;
+}
diff --git a/lib/public/Share/IShare.php b/lib/public/Share/IShare.php
index c19364c86c8..870794d6536 100644
--- a/lib/public/Share/IShare.php
+++ b/lib/public/Share/IShare.php
@@ -170,6 +170,40 @@ interface IShare {
public function getSharedWith();
/**
+ * Set the display name of the receiver of this share.
+ *
+ * @param string $displayName
+ * @return \OCP\Share\IShare The modified object
+ * @since 14.0.0
+ */
+ public function setSharedWithDisplayName($displayName);
+
+ /**
+ * Get the display name of the receiver of this share.
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function getSharedWithDisplayName();
+
+ /**
+ * Set the avatar of the receiver of this share.
+ *
+ * @param string $src
+ * @return \OCP\Share\IShare The modified object
+ * @since 14.0.0
+ */
+ public function setSharedWithAvatar($src);
+
+ /**
+ * Get the avatar of the receiver of this share.
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function getSharedWithAvatar();
+
+ /**
* Set the permissions.
* See \OCP\Constants::PERMISSION_*
*
diff --git a/settings/l10n/el.js b/settings/l10n/el.js
index b15b1ad7e68..8259e5ea743 100644
--- a/settings/l10n/el.js
+++ b/settings/l10n/el.js
@@ -174,6 +174,7 @@ OC.L10N.register(
"Start migration" : "Έναρξη μετάβασης",
"Security & setup warnings" : "Προειδοποιήσεις ασφάλειας & ρυθμίσεων",
"All checks passed." : "Όλοι οι έλεγχοι επιτυχείς.",
+ "There are some errors regarding your setup." : "Υπάρχουν μερικά σφάλματα σχετικά με τις ρυθμίσεις σας.",
"Version" : "Έκδοση",
"Background jobs" : "Εργασίες παρασκηνίου",
"Execute one task with each page loaded" : "Εκτελεί μια διεργασία κάθε φορά που φορτώνεται μια σελίδα",
diff --git a/settings/l10n/el.json b/settings/l10n/el.json
index 5abcf35ba2c..fbe91b1015d 100644
--- a/settings/l10n/el.json
+++ b/settings/l10n/el.json
@@ -172,6 +172,7 @@
"Start migration" : "Έναρξη μετάβασης",
"Security & setup warnings" : "Προειδοποιήσεις ασφάλειας & ρυθμίσεων",
"All checks passed." : "Όλοι οι έλεγχοι επιτυχείς.",
+ "There are some errors regarding your setup." : "Υπάρχουν μερικά σφάλματα σχετικά με τις ρυθμίσεις σας.",
"Version" : "Έκδοση",
"Background jobs" : "Εργασίες παρασκηνίου",
"Execute one task with each page loaded" : "Εκτελεί μια διεργασία κάθε φορά που φορτώνεται μια σελίδα",
diff --git a/settings/l10n/sl.js b/settings/l10n/sl.js
index a58622cdb68..0f560862e77 100644
--- a/settings/l10n/sl.js
+++ b/settings/l10n/sl.js
@@ -30,8 +30,8 @@ OC.L10N.register(
"Valid until {date}" : "Veljavno do {date}",
"Delete" : "Izbriši",
"Very weak password" : "Zelo šibko geslo",
- "Weak password" : "Šibko geslo",
- "So-so password" : "Slabo geslo",
+ "Weak password" : "Slabo geslo",
+ "So-so password" : "Šibko geslo",
"Good password" : "Dobro geslo",
"Strong password" : "Odlično geslo",
"Select a profile picture" : "Izbor slike profila",
diff --git a/settings/l10n/sl.json b/settings/l10n/sl.json
index 850b130ef7e..f5b75d32cd2 100644
--- a/settings/l10n/sl.json
+++ b/settings/l10n/sl.json
@@ -28,8 +28,8 @@
"Valid until {date}" : "Veljavno do {date}",
"Delete" : "Izbriši",
"Very weak password" : "Zelo šibko geslo",
- "Weak password" : "Šibko geslo",
- "So-so password" : "Slabo geslo",
+ "Weak password" : "Slabo geslo",
+ "So-so password" : "Šibko geslo",
"Good password" : "Dobro geslo",
"Strong password" : "Odlično geslo",
"Select a profile picture" : "Izbor slike profila",
diff --git a/tests/lib/L10N/FactoryTest.php b/tests/lib/L10N/FactoryTest.php
index 3008e0a239c..be842cf12c7 100644
--- a/tests/lib/L10N/FactoryTest.php
+++ b/tests/lib/L10N/FactoryTest.php
@@ -14,6 +14,7 @@ use OCP\IConfig;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserSession;
+use OCP\L10N\ILanguageIterator;
use Test\TestCase;
/**
@@ -596,4 +597,33 @@ class FactoryTest extends TestCase {
$this->assertSame($expected, $result);
}
+ public function languageIteratorRequestProvider():array {
+ return [
+ [ true, $this->createMock(IUser::class)],
+ [ false, $this->createMock(IUser::class)],
+ [ false, null]
+ ];
+ }
+
+ /**
+ * @dataProvider languageIteratorRequestProvider
+ */
+ public function testGetLanguageIterator(bool $hasSession, IUser $iUserMock = null) {
+ $factory = $this->getFactory();
+
+ if($iUserMock === null) {
+ $matcher = $this->userSession->expects($this->once())
+ ->method('getUser');
+
+ if($hasSession) {
+ $matcher->willReturn($this->createMock(IUser::class));
+ } else {
+ $this->expectException(\RuntimeException::class);
+ }
+ }
+
+ $iterator = $factory->getLanguageIterator($iUserMock);
+ $this->assertInstanceOf(ILanguageIterator::class, $iterator);
+ }
+
}
diff --git a/tests/lib/L10N/LanguageIteratorTest.php b/tests/lib/L10N/LanguageIteratorTest.php
new file mode 100644
index 00000000000..c8b1b24685f
--- /dev/null
+++ b/tests/lib/L10N/LanguageIteratorTest.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.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 Test\L10N;
+
+use OC\L10N\LanguageIterator;
+use OCP\IConfig;
+use OCP\IUser;
+use Test\TestCase;
+
+class LanguageIteratorTest extends TestCase {
+ /** @var IUser|\PHPUnit_Framework_MockObject_MockObject */
+ protected $user;
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
+ protected $config;
+ /** @var LanguageIterator */
+ protected $iterator;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->user = $this->createMock(IUser::class);
+ $this->config = $this->createMock(IConfig::class);
+
+ $this->iterator = new LanguageIterator($this->user, $this->config);
+ }
+
+ public function languageSettingsProvider() {
+ return [
+ // all language settings set
+ [ 'de_DE', 'es_CU', 'zh_TW', ['de_DE', 'de', 'es_CU', 'es', 'zh_TW', 'zh', 'en']],
+ [ 'de', 'es', 'zh', ['de', 'es', 'zh', 'en']],
+ [ 'en', 'en', 'en', ['en', 'en', 'en', 'en']],
+ // one possible setting is missing each
+ [ false, 'es_CU', 'zh_TW', ['es_CU', 'es', 'zh_TW', 'zh', 'en']],
+ [ false, 'es', 'zh_TW', ['es', 'zh_TW', 'zh', 'en']],
+ [ false, 'es_CU', 'zh', ['es_CU', 'es', 'zh', 'en']],
+ [ 'de_DE', null, 'zh_TW', ['de_DE', 'de', 'zh_TW', 'zh', 'en']],
+ [ 'de_DE', null, 'zh', ['de_DE', 'de', 'zh', 'en']],
+ [ 'de', null, 'zh_TW', ['de', 'zh_TW', 'zh', 'en']],
+ [ 'de_DE', 'es_CU', 'en', ['de_DE', 'de', 'es_CU', 'es', 'en', 'en']],
+ [ 'de', 'es_CU', 'en', ['de', 'es_CU', 'es', 'en', 'en']],
+ [ 'de_DE', 'es', 'en', ['de_DE', 'de', 'es', 'en', 'en']],
+ // two possible settings are missing each
+ [ false, null, 'zh_TW', ['zh_TW', 'zh', 'en']],
+ [ false, null, 'zh', ['zh', 'en']],
+ [ false, 'es_CU', 'en', ['es_CU', 'es', 'en', 'en']],
+ [ false, 'es', 'en', ['es', 'en', 'en']],
+ [ 'de_DE', null, 'en', ['de_DE', 'de', 'en', 'en']],
+ [ 'de', null, 'en', ['de', 'en', 'en']],
+ // nothing is set
+ [ false, null, 'en', ['en', 'en']],
+
+ ];
+ }
+
+ /**
+ * @dataProvider languageSettingsProvider
+ */
+ public function testIterator($forcedLang, $userLang, $sysLang, $expectedValues) {
+ $this->config->expects($this->any())
+ ->method('getSystemValue')
+ ->willReturnMap([
+ ['force_language', false, $forcedLang],
+ ['default_language', 'en', $sysLang],
+ ]);
+ $this->config->expects($this->any())
+ ->method('getUserValue')
+ ->willReturn($userLang);
+
+ foreach ($expectedValues as $expected) {
+ $this->assertTrue($this->iterator->valid());
+ $this->assertSame($expected, $this->iterator->current());
+ $this->iterator->next();
+ }
+ $this->assertFalse($this->iterator->valid());
+ }
+}
diff --git a/tests/lib/Share20/DefaultShareProviderTest.php b/tests/lib/Share20/DefaultShareProviderTest.php
index 0fa8aa3d0c6..230c8db40ce 100644
--- a/tests/lib/Share20/DefaultShareProviderTest.php
+++ b/tests/lib/Share20/DefaultShareProviderTest.php
@@ -629,6 +629,8 @@ class DefaultShareProviderTest extends \Test\TestCase {
$share->setSharedBy('sharedBy');
$share->setShareOwner('shareOwner');
$share->setNode($path);
+ $share->setSharedWithDisplayName('Displayed Name');
+ $share->setSharedWithAvatar('/path/to/image.svg');
$share->setPermissions(1);
$share->setTarget('/target');
@@ -644,6 +646,12 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertSame('/target', $share2->getTarget());
$this->assertLessThanOrEqual(new \DateTime(), $share2->getShareTime());
$this->assertSame($path, $share2->getNode());
+
+ // nothing from setSharedWithDisplayName/setSharedWithAvatar is saved in DB
+ $this->assertSame('Displayed Name', $share->getSharedWithDisplayName());
+ $this->assertSame('/path/to/image.svg', $share->getSharedWithAvatar());
+ $this->assertSame(null, $share2->getSharedWithDisplayName());
+ $this->assertSame(null, $share2->getSharedWithAvatar());
}
public function testCreateGroupShare() {
@@ -678,6 +686,8 @@ class DefaultShareProviderTest extends \Test\TestCase {
$share->setShareOwner('shareOwner');
$share->setNode($path);
$share->setPermissions(1);
+ $share->setSharedWithDisplayName('Displayed Name');
+ $share->setSharedWithAvatar('/path/to/image.svg');
$share->setTarget('/target');
$share2 = $this->provider->create($share);
@@ -692,6 +702,13 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertSame('/target', $share2->getTarget());
$this->assertLessThanOrEqual(new \DateTime(), $share2->getShareTime());
$this->assertSame($path, $share2->getNode());
+
+ // nothing from setSharedWithDisplayName/setSharedWithAvatar is saved in DB
+ $this->assertSame('Displayed Name', $share->getSharedWithDisplayName());
+ $this->assertSame('/path/to/image.svg', $share->getSharedWithAvatar());
+ $this->assertSame(null, $share2->getSharedWithDisplayName());
+ $this->assertSame(null, $share2->getSharedWithAvatar());
+
}
public function testCreateLinkShare() {
diff --git a/tests/lib/Updater/ChangesCheckTest.php b/tests/lib/Updater/ChangesCheckTest.php
index cbb298647d0..fe25e8cebaf 100644
--- a/tests/lib/Updater/ChangesCheckTest.php
+++ b/tests/lib/Updater/ChangesCheckTest.php
@@ -29,11 +29,11 @@ namespace Test\Updater;
use OC\Updater\ChangesCheck;
use OC\Updater\ChangesMapper;
use OC\Updater\ChangesResult;
+use OCP\AppFramework\Db\DoesNotExistException;
use OCP\Http\Client\IClient;
use OCP\Http\Client\IClientService;
use OCP\Http\Client\IResponse;
use OCP\ILogger;
-use const Solarium\QueryType\Select\Query\Component\Facet\INCLUDE_LOWER;
use Test\TestCase;
class ChangesCheckTest extends TestCase {
@@ -338,7 +338,42 @@ class ChangesCheckTest extends TestCase {
* @dataProvider versionProvider
*/
public function testNormalizeVersion(string $input, string $expected) {
- $normalized = $this->invokePrivate($this->checker, 'normalizeVersion', [$input]);
+ $normalized = $this->checker->normalizeVersion($input);
$this->assertSame($expected, $normalized);
}
+
+ public function changeDataProvider():array {
+ $testDataFound = $testDataNotFound = $this->versionProvider();
+ array_walk($testDataFound, function(&$params) { $params[] = true; });
+ array_walk($testDataNotFound, function(&$params) { $params[] = false; });
+ return array_merge($testDataFound, $testDataNotFound);
+ }
+
+ /**
+ * @dataProvider changeDataProvider
+ *
+ */
+ public function testGetChangesForVersion(string $inputVersion, string $normalizedVersion, bool $isFound) {
+ $mocker = $this->mapper->expects($this->once())
+ ->method('getChanges')
+ ->with($normalizedVersion);
+
+ if(!$isFound) {
+ $this->expectException(DoesNotExistException::class);
+ $mocker->willThrowException(new DoesNotExistException('Changes info is not present'));
+ } else {
+ $entry = $this->createMock(ChangesResult::class);
+ $entry->expects($this->once())
+ ->method('__call')
+ ->with('getData')
+ ->willReturn('{"changelogURL":"https:\/\/nextcloud.com\/changelog\/#13-0-0","whatsNew":{"en":{"regular":["Refined user interface","End-to-end Encryption","Video and Text Chat"],"admin":["Changes to the Nginx configuration","Theming: CSS files were consolidated"]},"de":{"regular":["\u00dcberarbeitete Benutzerschnittstelle","Ende-zu-Ende Verschl\u00fcsselung","Video- und Text-Chat"],"admin":["\u00c4nderungen an der Nginx Konfiguration","Theming: CSS Dateien wurden konsolidiert"]}}}');
+
+ $mocker->willReturn($entry);
+ }
+
+ /** @noinspection PhpUnhandledExceptionInspection */
+ $data = $this->checker->getChangesForVersion($inputVersion);
+ $this->assertTrue(isset($data['whatsNew']['en']['regular']));
+ $this->assertTrue(isset($data['changelogURL']));
+ }
}