diff --git a/app.js b/app.js
index cf4d0d97f2..1c7e5017d5 100644
--- a/app.js
+++ b/app.js
@@ -35,7 +35,7 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'production';
global.env = process.env.NODE_ENV || 'production';
// Alternate configuration file support
-const configFile = path.resolve(__dirname, nconf.any(['config', 'CONFIG']) || 'config.json');
+const configFile = path.resolve(__dirname, nconf.any(['config', 'CONFIG']) || 'config.json');
const configExists = file.existsSync(configFile) || (nconf.get('url') && nconf.get('secret') && nconf.get('database'));
diff --git a/install/package.json b/install/package.json
index f784334cc0..f7974b6ca9 100644
--- a/install/package.json
+++ b/install/package.json
@@ -87,12 +87,12 @@
"nodebb-plugin-markdown": "8.11.2",
"nodebb-plugin-mentions": "2.7.4",
"nodebb-plugin-soundpack-default": "1.0.0",
- "nodebb-plugin-spam-be-gone": "0.7.1",
+ "nodebb-plugin-spam-be-gone": "0.7.2",
"nodebb-rewards-essentials": "0.1.3",
"nodebb-theme-lavender": "5.0.11",
- "nodebb-theme-persona": "10.1.53",
+ "nodebb-theme-persona": "10.1.54",
"nodebb-theme-slick": "1.2.29",
- "nodebb-theme-vanilla": "11.1.28",
+ "nodebb-theme-vanilla": "11.1.29",
"nodebb-widget-essentials": "4.1.0",
"nodemailer": "^6.4.6",
"passport": "^0.4.1",
@@ -126,15 +126,15 @@
"toobusy-js": "^0.5.1",
"uglify-es": "^3.3.9",
"validator": "13.1.1",
- "winston": "3.2.1",
+ "winston": "3.3.2",
"xml": "^1.0.1",
"xregexp": "^4.3.0",
"zxcvbn": "^4.4.2"
},
"devDependencies": {
"@apidevtools/swagger-parser": "9.0.1",
- "@commitlint/cli": "8.3.5",
- "@commitlint/config-angular": "8.3.4",
+ "@commitlint/cli": "9.0.1",
+ "@commitlint/config-angular": "9.0.1",
"coveralls": "3.1.0",
"eslint": "7.2.0",
"eslint-config-airbnb-base": "14.1.0",
@@ -143,7 +143,7 @@
"grunt-contrib-watch": "1.1.0",
"husky": "4.2.5",
"jsdom": "16.2.2",
- "lint-staged": "10.2.10",
+ "lint-staged": "10.2.11",
"mocha": "8.0.1",
"mocha-lcov-reporter": "1.3.0",
"nyc": "15.0.1",
diff --git a/install/web.js b/install/web.js
index 56bf322a92..0bccdc1847 100644
--- a/install/web.js
+++ b/install/web.js
@@ -81,7 +81,7 @@ web.install = function (port) {
async.parallel([compileLess, compileJS, copyCSS, loadDefaults], function (err) {
if (err) {
- winston.error(err);
+ winston.error(err.stack);
}
setupRoutes();
launchExpress(port);
@@ -225,12 +225,12 @@ function launch(req, res) {
function compileLess(callback) {
fs.readFile(path.join(__dirname, '../public/less/install.less'), function (err, style) {
if (err) {
- return winston.error('Unable to read LESS install file: ', err);
+ return winston.error('Unable to read LESS install file: ', err.stack);
}
less.render(style.toString(), function (err, css) {
if (err) {
- return winston.error('Unable to compile LESS: ', err);
+ return winston.error('Unable to compile LESS: ', err.stack);
}
fs.writeFile(path.join(__dirname, '../public/installer.css'), css.css, callback);
diff --git a/public/language/ar/flags.json b/public/language/ar/flags.json
index 83661216d5..cfa96c834a 100644
--- a/public/language/ar/flags.json
+++ b/public/language/ar/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/ar/notifications.json b/public/language/ar/notifications.json
index 0c86cd65f8..71ae442723 100644
--- a/public/language/ar/notifications.json
+++ b/public/language/ar/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "There are %1 registration requests awaiting review.",
"flag_assigned_to_you": "تم تخصيص العلامة 1% لك",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "تم التحقق من عنوان البريد الإلكتروني",
"email-confirmed-message": "شكرًا على إثبات صحة عنوان بريدك الإلكتروني. صار حسابك مفعلًا بالكامل.",
"email-confirm-error-message": "حدث خطأ أثناء التحقق من عنوان بريدك الإلكتروني. ربما رمز التفعيل خاطئ أو انتهت صلاحيته.",
diff --git a/public/language/ar/user.json b/public/language/ar/user.json
index af7b2f0dda..463dca997e 100644
--- a/public/language/ar/user.json
+++ b/public/language/ar/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/bg/flags.json b/public/language/bg/flags.json
index 1e10757d15..58aaf0e35f 100644
--- a/public/language/bg/flags.json
+++ b/public/language/bg/flags.json
@@ -45,7 +45,6 @@
"no-notes": "Няма споделени бележки.",
"history": "Акаунт и история на докладванията",
- "back": "Обратно към списъка с доклади",
"no-history": "Няма история на доклада.",
"state-all": "Всички състояния",
diff --git a/public/language/bg/notifications.json b/public/language/bg/notifications.json
index dd195e5cb2..ea0beadaff 100644
--- a/public/language/bg/notifications.json
+++ b/public/language/bg/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Има %1 заявки за регистрация, които очакват да бъдат прегледани.",
"flag_assigned_to_you": "Докладът %1 беше назначен на Вас",
"post_awaiting_review": "Публикацията чака да бъде прегледана",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Е-пощата беше потвърдена",
"email-confirmed-message": "Благодарим Ви, че потвърдихте е-пощата си. Акаунтът Ви е вече напълно активиран.",
"email-confirm-error-message": "Възникна проблем при потвърждаването на е-пощата Ви. Може кодът да е грешен или давността му да е изтекла.",
diff --git a/public/language/bg/user.json b/public/language/bg/user.json
index 714b7816ab..07a8c00996 100644
--- a/public/language/bg/user.json
+++ b/public/language/bg/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "Имате право на пренос на данни",
"consent.right_to_data_portability_description": "Можете да изискате от нас всички събрани за Вас и акаунта Ви данни в машинен формат. Можете да направите това като натиснете съответния бутон по-долу.",
"consent.export_profile": "Изнасяне на профила (.json)",
+ "consent.export-profile-success": "Изнасяне на профила… Ще получите известие, когато е готово.",
"consent.export_uploads": "Изнасяне на каченото съдържание (.zip)",
- "consent.export_posts": "Изнасяне на публикациите (.csv)"
+ "consent.export-uploads-success": "Изнасяне на каченото съдържание… Ще получите известие, когато е готово.",
+ "consent.export_posts": "Изнасяне на публикациите (.csv)",
+ "consent.export-posts-success": "Изнасяне на публикациите… Ще получите известие, когато е готово."
}
\ No newline at end of file
diff --git a/public/language/bn/flags.json b/public/language/bn/flags.json
index b3561f9e38..fb8708fc16 100644
--- a/public/language/bn/flags.json
+++ b/public/language/bn/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/bn/notifications.json b/public/language/bn/notifications.json
index a11e62bc4c..f17cd098c2 100644
--- a/public/language/bn/notifications.json
+++ b/public/language/bn/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "There are %1 registration requests awaiting review.",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "ইমেইল নিশ্চিত করা হয়েছে",
"email-confirmed-message": "আপনার ইমেইল যাচাই করার জন্য আপনাকে ধন্যবাদ। আপনার অ্যাকাউন্টটি এখন সম্পূর্ণরূপে সক্রিয়।",
"email-confirm-error-message": "আপনার ইমেল ঠিকানার বৈধতা যাচাইয়ে একটি সমস্যা হয়েছে। সম্ভবত কোডটি ভুল ছিল অথবা কোডের মেয়াদ শেষ হয়ে গিয়েছে।",
diff --git a/public/language/bn/user.json b/public/language/bn/user.json
index c0bd82e3d9..b715f10cc9 100644
--- a/public/language/bn/user.json
+++ b/public/language/bn/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/cs/flags.json b/public/language/cs/flags.json
index 9ee580e597..6039875435 100644
--- a/public/language/cs/flags.json
+++ b/public/language/cs/flags.json
@@ -45,7 +45,6 @@
"no-notes": "Žádné sdílené poznámky.",
"history": "Account & Flag History",
- "back": "Zpět k seznamu označení",
"no-history": "Žádná historie označení.",
"state-all": "Všechny stavy",
diff --git a/public/language/cs/notifications.json b/public/language/cs/notifications.json
index 277095f420..662cf1541d 100644
--- a/public/language/cs/notifications.json
+++ b/public/language/cs/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Je zde %1 registračních požadavků čeká na vyřízení.",
"flag_assigned_to_you": "Označení %1 vám bylo přiřazeno",
"post_awaiting_review": "Příspěvek na schválení",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "E-mail potvrzen",
"email-confirmed-message": "Děkujeme za ověření vaší e-mailové adresy. Váš účet je nyní aktivní.",
"email-confirm-error-message": "Nastal problém s ověřením vaší e-mailové adresy. Kód je pravděpodobně neplatný nebo jeho platnost vypršela.",
diff --git a/public/language/cs/user.json b/public/language/cs/user.json
index fe2b1adcee..a7eb17acaa 100644
--- a/public/language/cs/user.json
+++ b/public/language/cs/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "Máte právo na přenositelnost dat",
"consent.right_to_data_portability_description": "Můžete od nás požadovat strojně čitelné data, která byla sesbírána o Vás a vašem účtu. Učiníte tak kliknutím na tlačítka zobrazená níže.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Exportovat nahraný obsah (*.zip)",
- "consent.export_posts": "Exportovat příspěvky (*.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Exportovat příspěvky (*.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/da/flags.json b/public/language/da/flags.json
index b3561f9e38..fb8708fc16 100644
--- a/public/language/da/flags.json
+++ b/public/language/da/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/da/notifications.json b/public/language/da/notifications.json
index 51a44a8f0e..e18b411132 100644
--- a/public/language/da/notifications.json
+++ b/public/language/da/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "There are %1 registration requests awaiting review.",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Email bekræftet",
"email-confirmed-message": "Tak fordi du validerede din email. Din konto er nu fuldt ud aktiveret.",
"email-confirm-error-message": "Der var et problem med valideringen af din emailadresse. Bekræftelses koden var muligvis forkert eller udløbet.",
diff --git a/public/language/da/user.json b/public/language/da/user.json
index b2ec2d9a14..8ded88934a 100644
--- a/public/language/da/user.json
+++ b/public/language/da/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/de/flags.json b/public/language/de/flags.json
index a7834d988f..0e5fee92b8 100644
--- a/public/language/de/flags.json
+++ b/public/language/de/flags.json
@@ -45,7 +45,6 @@
"no-notes": "Keine geteilten Notizen",
"history": "Account & Flag History",
- "back": "Zurück zur Meldungsliste",
"no-history": "Kein Meldungsverlauf",
"state-all": "Alle Status",
diff --git a/public/language/de/notifications.json b/public/language/de/notifications.json
index b9fbf859da..21b9cd06cf 100644
--- a/public/language/de/notifications.json
+++ b/public/language/de/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Es erwarten %1 Registrierungsanfragen eine Überprüfung.",
"flag_assigned_to_you": "Markierung %1 wurde Ihnen zugewiesen",
"post_awaiting_review": "Beitrag noch nicht Überprüft",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "E-Mail bestätigt",
"email-confirmed-message": "Vielen Dank für Ihre E-Mail-Validierung. Ihr Konto ist nun vollständig aktiviert.",
"email-confirm-error-message": "Es gab ein Problem bei der Validierung Ihrer E-Mail-Adresse. Möglicherweise ist der Code ungültig oder abgelaufen.",
diff --git a/public/language/de/user.json b/public/language/de/user.json
index 97a3c79cda..0089e8b72a 100644
--- a/public/language/de/user.json
+++ b/public/language/de/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "Du hast das Recht auf Datenportabilität",
"consent.right_to_data_portability_description": "Du kannst von uns eine Maschinen-Lesbare Datei von jeglichen gesammelten Daten von dir und deinem Konto anfordern, indem du unten auf den entsprechenden Knopf drückst. ",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Hochgeladene Dateien exportieren (.zip)",
- "consent.export_posts": "Beiträge exportieren (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Beiträge exportieren (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/el/flags.json b/public/language/el/flags.json
index b3561f9e38..fb8708fc16 100644
--- a/public/language/el/flags.json
+++ b/public/language/el/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/el/notifications.json b/public/language/el/notifications.json
index fa538d29b6..85efcdc2ed 100644
--- a/public/language/el/notifications.json
+++ b/public/language/el/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "There are %1 registration requests awaiting review.",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Email Confirmed",
"email-confirmed-message": "Thank you for validating your email. Your account is now fully activated.",
"email-confirm-error-message": "There was a problem validating your email address. Perhaps the code was invalid or has expired.",
diff --git a/public/language/el/user.json b/public/language/el/user.json
index 734609fe37..b3d73cf6a1 100644
--- a/public/language/el/user.json
+++ b/public/language/el/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/en-GB/notifications.json b/public/language/en-GB/notifications.json
index 7ce5515ca0..3b9e656c0c 100644
--- a/public/language/en-GB/notifications.json
+++ b/public/language/en-GB/notifications.json
@@ -47,6 +47,9 @@
"new_register_multiple": "There are %1 registration requests awaiting review.",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Email Confirmed",
"email-confirmed-message": "Thank you for validating your email. Your account is now fully activated.",
diff --git a/public/language/en-GB/user.json b/public/language/en-GB/user.json
index 448831efd4..78122022fb 100644
--- a/public/language/en-GB/user.json
+++ b/public/language/en-GB/user.json
@@ -200,6 +200,9 @@
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
diff --git a/public/language/en-US/flags.json b/public/language/en-US/flags.json
index b3561f9e38..fb8708fc16 100644
--- a/public/language/en-US/flags.json
+++ b/public/language/en-US/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/en-US/notifications.json b/public/language/en-US/notifications.json
index 980fdbc964..91600bf79a 100644
--- a/public/language/en-US/notifications.json
+++ b/public/language/en-US/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "There are %1 registration requests awaiting review.",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Email Confirmed",
"email-confirmed-message": "Thank you for validating your email. Your account is now fully activated.",
"email-confirm-error-message": "There was a problem validating your email address. Perhaps the code was invalid or has expired.",
diff --git a/public/language/en-US/user.json b/public/language/en-US/user.json
index ced3efe3a2..d100a99ad9 100644
--- a/public/language/en-US/user.json
+++ b/public/language/en-US/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/en-x-pirate/flags.json b/public/language/en-x-pirate/flags.json
index b3561f9e38..fb8708fc16 100644
--- a/public/language/en-x-pirate/flags.json
+++ b/public/language/en-x-pirate/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/en-x-pirate/notifications.json b/public/language/en-x-pirate/notifications.json
index 0d57170235..705fed3063 100644
--- a/public/language/en-x-pirate/notifications.json
+++ b/public/language/en-x-pirate/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "There are %1 registration requests awaiting review.",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Email Confirmed",
"email-confirmed-message": "Thank you for validating your email. Your account is now fully activated.",
"email-confirm-error-message": "There was a problem validating your email address. Perhaps the code was invalid or has expired.",
diff --git a/public/language/en-x-pirate/user.json b/public/language/en-x-pirate/user.json
index 92fad5db1a..8bfa716d2d 100644
--- a/public/language/en-x-pirate/user.json
+++ b/public/language/en-x-pirate/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/es/flags.json b/public/language/es/flags.json
index b339d0ba53..b9fb0e7a8a 100644
--- a/public/language/es/flags.json
+++ b/public/language/es/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No hay notas compartidas",
"history": "Account & Flag History",
- "back": "Volver a la lista de marcadores",
"no-history": "No hay registro de marcadores",
"state-all": "Todos los estados",
diff --git a/public/language/es/notifications.json b/public/language/es/notifications.json
index 4527ea84a3..6dc1c86b19 100644
--- a/public/language/es/notifications.json
+++ b/public/language/es/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Hay %1 peticiones de registros pendientes de revisión",
"flag_assigned_to_you": "Reporte %1 te ha sido asignado.",
"post_awaiting_review": "Entrada esperando revisión",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Correo electrónico confirmado",
"email-confirmed-message": "Gracias por validar tu correo electrónico. Tu cuenta ya está completamente activa.",
"email-confirm-error-message": "Hubo un problema al validar tu cuenta de correo electrónico. Quizá el código era erróneo o expiró...",
diff --git a/public/language/es/user.json b/public/language/es/user.json
index b99a143d75..06af0f5634 100644
--- a/public/language/es/user.json
+++ b/public/language/es/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "Usted tiene el Derecho a la Portabilidad de Datos",
"consent.right_to_data_portability_description": "Puede pedir de nosotros una exportación legible por máquinas de cualquier dato recolectado sobre usted y su cuenta. Puede hacerlo haciendo click en el botón apropiado abajo.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Exportar Contenido Subido (.zip)",
- "consent.export_posts": "Exportar Entradas y Respuestas (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Exportar Entradas y Respuestas (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/et/flags.json b/public/language/et/flags.json
index b3561f9e38..fb8708fc16 100644
--- a/public/language/et/flags.json
+++ b/public/language/et/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/et/notifications.json b/public/language/et/notifications.json
index a3377197d2..43a8469320 100644
--- a/public/language/et/notifications.json
+++ b/public/language/et/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "%1 registreerimistaotlust ootavad ülevaadet.",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Emaili aadress kinnitatud",
"email-confirmed-message": "Täname, et kinnitasite oma emaili aadressi. Teie kasutaja on nüüd täielikult aktiveeritud.",
"email-confirm-error-message": "Emaili aadressi kinnitamisel tekkis viga. Võibolla kinnituskood oli vale või aegunud.",
diff --git a/public/language/et/user.json b/public/language/et/user.json
index 7fc7fbc85a..ea2135af96 100644
--- a/public/language/et/user.json
+++ b/public/language/et/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/fa-IR/flags.json b/public/language/fa-IR/flags.json
index 429cc12b9c..c5bbd72983 100644
--- a/public/language/fa-IR/flags.json
+++ b/public/language/fa-IR/flags.json
@@ -45,7 +45,6 @@
"no-notes": "بدون یادداشت",
"history": "Account & Flag History",
- "back": "بازگشت به لیست گزارش ها",
"no-history": "بدون تاریخچه گزارش",
"state-all": "همه وضعیت ها",
diff --git a/public/language/fa-IR/notifications.json b/public/language/fa-IR/notifications.json
index e31af582ed..aff9a5edb1 100644
--- a/public/language/fa-IR/notifications.json
+++ b/public/language/fa-IR/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "تعداد %1 درخواست عضویت برای بررسی وجود دارد.",
"flag_assigned_to_you": "گزارش %1به شما تعلق گرفت",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "ایمیل تایید شد",
"email-confirmed-message": "بابت تایید ایمیلتان سپاسگزاریم. حساب کاربری شما اکنون به صورت کامل فعال شده است.",
"email-confirm-error-message": "خطایی در تایید آدرس ایمیل شما پیش آمده است. ممکن است کد نامعتبر و یا منقضی شده باشد.",
diff --git a/public/language/fa-IR/user.json b/public/language/fa-IR/user.json
index 55c40eddd8..491eeb9eeb 100644
--- a/public/language/fa-IR/user.json
+++ b/public/language/fa-IR/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/fi/flags.json b/public/language/fi/flags.json
index b3561f9e38..fb8708fc16 100644
--- a/public/language/fi/flags.json
+++ b/public/language/fi/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/fi/notifications.json b/public/language/fi/notifications.json
index 0118d76edf..be327e7527 100644
--- a/public/language/fi/notifications.json
+++ b/public/language/fi/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "%1 rekisteröintipyyntöä odottaa katselmointia",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Viesti odottaa katselmointia",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Sähköpostiosoite vahvistettu",
"email-confirmed-message": "Kiitos sähköpostiosoitteesi vahvistamisesta. Käyttäjätilisi on nyt täysin aktivoitu.",
"email-confirm-error-message": "Ongelma sähköpostiosoitteen vahvistamisessa. Ehkäpä koodi oli virheellinen tai vanhentunut.",
diff --git a/public/language/fi/user.json b/public/language/fi/user.json
index d3877eb780..045a2e2c78 100644
--- a/public/language/fi/user.json
+++ b/public/language/fi/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/fr/flags.json b/public/language/fr/flags.json
index b580cb0fa0..e8412bcd22 100644
--- a/public/language/fr/flags.json
+++ b/public/language/fr/flags.json
@@ -45,7 +45,6 @@
"no-notes": "aucune note partagée",
"history": "Compte & Historique des signalements",
- "back": "Revenir à la liste des signalements",
"no-history": "aucun historique de signalements",
"state-all": "Tous les états",
diff --git a/public/language/fr/notifications.json b/public/language/fr/notifications.json
index 312ca64b86..b51e163cda 100644
--- a/public/language/fr/notifications.json
+++ b/public/language/fr/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "%1 inscription(s) est en attente de validation.",
"flag_assigned_to_you": "Drapeau %1 vous a été assigné",
"post_awaiting_review": "Message en attente de validation",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Email vérifié",
"email-confirmed-message": "Merci pour la validation de votre adresse email. Votre compte est désormais activé.",
"email-confirm-error-message": "Il y a un un problème dans la vérification de votre adresse email. Le code est peut être invalide ou a expiré.",
diff --git a/public/language/fr/user.json b/public/language/fr/user.json
index ff9f834182..b189a4ac8b 100644
--- a/public/language/fr/user.json
+++ b/public/language/fr/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "Vous avez la possibilité de portabilité des données.",
"consent.right_to_data_portability_description": "Vous pouvez exporter de toutes vos données collectées. Vous pouvez le faire en cliquant sur le bouton ci-dessous.",
"consent.export_profile": "Exporter Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Exporter le contenu de vos fichiers envoyés (.zip)",
- "consent.export_posts": "Exporter vos messages (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Exporter vos messages (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/gl/flags.json b/public/language/gl/flags.json
index 783a6b03f2..1667007a0d 100644
--- a/public/language/gl/flags.json
+++ b/public/language/gl/flags.json
@@ -45,7 +45,6 @@
"no-notes": "Ningunha nota foi compartida",
"history": "Account & Flag History",
- "back": "Voltar á lista de avisos",
"no-history": "Non hai historial de avisos",
"state-all": "Tódolos estados",
diff --git a/public/language/gl/notifications.json b/public/language/gl/notifications.json
index 4267d4afdb..6470a1fd96 100644
--- a/public/language/gl/notifications.json
+++ b/public/language/gl/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Hai %1 peticións de rexistros pendentes de revisión",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Correo confirmado",
"email-confirmed-message": "Grazas por validar o teu correo. A túa conta agora está activada.",
"email-confirm-error-message": "Houbo un problema validando o teu correo. Poida que o código fose inválido ou expirase. ",
diff --git a/public/language/gl/user.json b/public/language/gl/user.json
index e47a0d2273..a43e9af2c3 100644
--- a/public/language/gl/user.json
+++ b/public/language/gl/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/he/flags.json b/public/language/he/flags.json
index cb05e6d082..f608495cc7 100644
--- a/public/language/he/flags.json
+++ b/public/language/he/flags.json
@@ -45,7 +45,6 @@
"no-notes": "אין הערות",
"history": "Account & Flag History",
- "back": "חזרה לרשימת הסימונים",
"no-history": "אין הסיטוריית סימונים",
"state-all": "כל המצבים",
diff --git a/public/language/he/notifications.json b/public/language/he/notifications.json
index cfbf0734b3..58596f5a8a 100644
--- a/public/language/he/notifications.json
+++ b/public/language/he/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "ישנן %1 בקשות הרשמה שמחכות לבדיקה.",
"flag_assigned_to_you": "דיווח %1 הוקצה עבורך",
"post_awaiting_review": "הפוסט ממתין לאישור",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "כתובת המייל אושרה",
"email-confirmed-message": "תודה שאישרת את כתובת המייל שלך. החשבון שלך פעיל כעת.",
"email-confirm-error-message": "אירעה שגיאה בעת אישור המייל שלך. ייתכן כי הקוד היה שגוי או פג תוקף.",
diff --git a/public/language/he/user.json b/public/language/he/user.json
index 9e2810dff9..4868476155 100644
--- a/public/language/he/user.json
+++ b/public/language/he/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "זכותך לניוד הנתונים",
"consent.right_to_data_portability_description": "באפרותך לבקש ייצוא של כל הנתונים שנאספו מחשבונך אודותיך. תוכל לעשות זאת על ידי לחיצה על הלחצן המתאים מטה.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "יצוא תוכן שהועלה (ZIP.)",
- "consent.export_posts": "יצוא פוסטים (CVS.)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "יצוא פוסטים (CVS.)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/hr/flags.json b/public/language/hr/flags.json
index d3a988e042..6ae25dc7d9 100644
--- a/public/language/hr/flags.json
+++ b/public/language/hr/flags.json
@@ -45,7 +45,6 @@
"no-notes": "Nema podijeljenih bilješki",
"history": "Account & Flag History",
- "back": "Nazad na popis zastava",
"no-history": "Nema povijesti zastava.",
"state-all": "Sva stanja",
diff --git a/public/language/hr/notifications.json b/public/language/hr/notifications.json
index 62e5a7e026..85f031bab3 100644
--- a/public/language/hr/notifications.json
+++ b/public/language/hr/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "%1 registracija čeka odobrenje.",
"flag_assigned_to_you": "Zastava%1 je dodijeljena vama.",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Email potvrđen",
"email-confirmed-message": "Hvala na potvrdi emaila. Vaš račun je sada aktivan.",
"email-confirm-error-message": "Nastao je problem pri potvrdi Vaše email adrese. Provjerite kod ili zatražite novi.",
diff --git a/public/language/hr/user.json b/public/language/hr/user.json
index 679c8f8871..653fda68db 100644
--- a/public/language/hr/user.json
+++ b/public/language/hr/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/hu/flags.json b/public/language/hu/flags.json
index 4bf0096963..c7fd042b99 100644
--- a/public/language/hu/flags.json
+++ b/public/language/hu/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/hu/notifications.json b/public/language/hu/notifications.json
index 78bf732d42..71e4edd6a2 100644
--- a/public/language/hu/notifications.json
+++ b/public/language/hu/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Jelenleg %1 regisztrációs kérvény vár elbírálásra.",
"flag_assigned_to_you": "%1 megjelölés hozzád van társítva",
"post_awaiting_review": "A hozzászólás átnézésre vár",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "E-mail megerősítve",
"email-confirmed-message": "Köszönjük az e-mail címed megerősítését. A fiókod mostantól teljesen aktiválva van.",
"email-confirm-error-message": "Probléma lépett fel az e-mail címed megerősítésekor. Talán a kód érvénytelen volt vagy lejárt.",
diff --git a/public/language/hu/user.json b/public/language/hu/user.json
index 675ddcacd4..ba1ff56551 100644
--- a/public/language/hu/user.json
+++ b/public/language/hu/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "Jogodban áll az adathordozhatóság",
"consent.right_to_data_portability_description": "Kérelmezhetsz tőlünk egy gép által olvasható kivonatot bármilyen, a rólad és fiókodról gyűjtött adatról. Ezt alább a megfelelő gomb megnyomásával teheted meg.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Feltöltött tartalom exportálása (.zip)",
- "consent.export_posts": "Hozzászólások exportálása (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Hozzászólások exportálása (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/id/flags.json b/public/language/id/flags.json
index b3561f9e38..fb8708fc16 100644
--- a/public/language/id/flags.json
+++ b/public/language/id/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/id/notifications.json b/public/language/id/notifications.json
index 27e3026ee7..2192cce6cc 100644
--- a/public/language/id/notifications.json
+++ b/public/language/id/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "There are %1 registration requests awaiting review.",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Email telah Dikonfirmasi",
"email-confirmed-message": "Terimakasih telah melakukan validasi email. Akunmu saat ini telah aktif sepenuhnya.",
"email-confirm-error-message": "Terjadi masalah saat melakukan validasi emailmu. Mungkin terjadi kesalahan kode atau waktu habis.",
diff --git a/public/language/id/user.json b/public/language/id/user.json
index fd1c13acca..9223a72a6e 100644
--- a/public/language/id/user.json
+++ b/public/language/id/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/it/admin/manage/digest.json b/public/language/it/admin/manage/digest.json
index e025712808..3f5f105d7b 100644
--- a/public/language/it/admin/manage/digest.json
+++ b/public/language/it/admin/manage/digest.json
@@ -9,7 +9,7 @@
"default": "Sistema predefinito",
"default-help": "Sistema predefinito significa che l'utente non ha esplicitamente sovrascritto l'impostazione del forum globale per i digest, che attualmente è: & quot;%1"",
"resend": "Rinvia Digest",
- "resend-all-confirm": "Are you sure you wish to manually execute this digest run?",
+ "resend-all-confirm": "Sei sicuro di voler eseguire manualmente questa esecuzione del riepilogo?",
"resent-single": "Invio del digest manuale completato",
"resent-day": "Rinvio digest giornaliero",
"resent-week": "Rinvio del digest settimanale",
diff --git a/public/language/it/admin/manage/privileges.json b/public/language/it/admin/manage/privileges.json
index 9c0ed06dda..fed64850b2 100644
--- a/public/language/it/admin/manage/privileges.json
+++ b/public/language/it/admin/manage/privileges.json
@@ -1,7 +1,7 @@
{
"global": "Globale",
"global.no-users": "Nessun privilegio globale specifico per l'utente.",
- "admin": "Admin",
+ "admin": "Amministratore",
"group-privileges": "Privilegi di gruppo",
"user-privileges": "Privilegi utente",
"chat": "Chat",
@@ -35,8 +35,8 @@
"moderate": "Moderata",
"admin-dashboard": "Dashboard",
- "admin-categories": "Categories",
- "admin-privileges": "Privileges",
- "admin-users": "Users",
- "admin-settings": "Settings"
+ "admin-categories": "Categorie",
+ "admin-privileges": "Privilegi",
+ "admin-users": "Utenti",
+ "admin-settings": "Impostazioni"
}
\ No newline at end of file
diff --git a/public/language/it/admin/manage/tags.json b/public/language/it/admin/manage/tags.json
index 2964592957..330fb2b6d4 100644
--- a/public/language/it/admin/manage/tags.json
+++ b/public/language/it/admin/manage/tags.json
@@ -3,13 +3,13 @@
"bg-color": "Colore di sfondo",
"text-color": "Colore del testo",
"create-modify": "Crea e modifica i tag",
- "description": "Select tags by clicking or dragging, use CTRL to select multiple tags.",
+ "description": "Seleziona i tag facendo clic o trascinando, utilizza CTRL per selezionare più tag.",
"create": "Crea tag",
"modify": "Modifica i tag",
"rename": "Rinomina i tag",
"delete": "Elimina i tag selezionati",
"search": "Ricerca per tag...",
- "settings": "Tags Settings",
+ "settings": "Impostazioni tag",
"name": "Nome Tag",
"alerts.editing": "Modifica tag(s)",
diff --git a/public/language/it/admin/manage/users.json b/public/language/it/admin/manage/users.json
index 6db19e320b..45f0077c80 100644
--- a/public/language/it/admin/manage/users.json
+++ b/public/language/it/admin/manage/users.json
@@ -12,9 +12,9 @@
"unban": "Togli Ban Utente(i)",
"reset-lockout": "Reset Blocco",
"reset-flags": "Reset segnalazioni",
- "delete": "Delete User(s)",
- "delete-content": "Delete User(s) Content",
- "purge": "Delete User(s) and Content",
+ "delete": "EliminaUtente(i)",
+ "delete-content": "Elimina contenuto utente/i",
+ "purge": "Elimina Utenti e Contenuto",
"download-csv": "Scarica CSV",
"manage-groups": "Gestisci Gruppi",
"add-group": "Aggiungi Gruppo",
@@ -94,11 +94,11 @@
"alerts.validate-email-success": "Email validate",
"alerts.validate-force-password-reset-success": "Le password degli utenti sono resettate e la loro sessione è revocata.",
"alerts.password-reset-confirm": "Vuoi realmente inviare il reset della(e) password via email per questo(i) utente(i)",
- "alerts.confirm-delete": "Warning!
Do you really want to delete user(s)?
This action is not reversible! Only the user account will be deleted, their posts and topics will remain.
",
+ "alerts.confirm-delete": "Avvertimento!Vuoi davvero eliminare l'utente(i)?
Questa azione non è reversibile! Solo l'account utente sarà eliminato, i suoi post e le sue discussioni rimarranno.
",
"alerts.delete-success": "Utente(i) Cancellato(i)",
- "alerts.confirm-delete-content": "Warning!Do you really want to delete these user(s) content?
This action is not reversible! The users' accounts will remain, but their posts and topics will be deleted.
",
- "alerts.delete-content-success": "User(s) Content Deleted!",
- "alerts.confirm-purge": "Warning!Do you really want to delete user(s) and their content?
This action is not reversible! All user data and content will be erased!
",
+ "alerts.confirm-delete-content": "Avvertimento!Vuoi davvero eliminare il contenuto di questo utente(i)?Questa azione non è reversibile! Gli account degli utenti rimarranno, ma i loro post e discussioni saranno eliminati.",
+ "alerts.delete-content-success": "Contenuto dell'utente(i) eliminato!",
+ "alerts.confirm-purge": "Avvertimento!
Vuoi davvero eliminare l'utente(i) e il suo contenuto?
Questa azione non è reversibile! Tutti i dati e i contenuti dell'utente saranno cancellati!
",
"alerts.create": "Utente creato",
"alerts.button-create": "Crea",
"alerts.button-cancel": "Cancella",
diff --git a/public/language/it/admin/settings/advanced.json b/public/language/it/admin/settings/advanced.json
index a31e71fae7..50facc6dc0 100644
--- a/public/language/it/admin/settings/advanced.json
+++ b/public/language/it/admin/settings/advanced.json
@@ -15,12 +15,12 @@
"headers.acah": "Access-Control-Allow-Headers",
"hsts": "Rigorosa sicurezza trasporto",
"hsts.enabled": "Abilita HSTS (consigliato)",
- "hsts.maxAge": "HSTS Max Age",
+ "hsts.maxAge": "Età massima HSTS",
"hsts.subdomains": "Includi i sottodomini nell'intestazione HSTS",
"hsts.preload": "Consenti la precarica dell'intestazione HSTS",
"hsts.help": "Se abilitato, sarà impostata un'intestazione HSTS per questo sito. Puoi scegliere di includere sottodomini e segnalazioni di precaricamento nell'intestazione. In caso di dubbio, puoi lasciarle deselezionate. Più informazioni ",
"traffic-management": "Gestione Traffico",
- "traffic.help": "NodeBB uses a module that automatically denies requests in high-traffic situations. You can tune these settings here, although the defaults are a good starting point.",
+ "traffic.help": "NodeBB utilizza un modulo che nega automaticamente le richieste in situazioni di traffico elevato. È possibile regolare queste impostazioni qui, anche se le impostazioni predefinite sono un buon punto di partenza.",
"traffic.enable": "Abilita Gestione Traffico",
"traffic.event-lag": "Soglia ritardo ciclo eventi (in millisecondi)",
"traffic.event-lag-help": "L'abbassamento di questo valore diminuisce i tempi di attesa per il caricamento della pagina, ma mostrerà il messaggio \"carico eccessivo\" a più utenti. (Necessario riavviare)",
diff --git a/public/language/it/admin/settings/group.json b/public/language/it/admin/settings/group.json
index cd53856149..651295843c 100644
--- a/public/language/it/admin/settings/group.json
+++ b/public/language/it/admin/settings/group.json
@@ -3,7 +3,7 @@
"private-groups": "Gruppi Privati",
"private-groups.help": "Se abilitato, l'iscrizione ai gruppi richiede l'approvazione del proprietario del gruppo (Predefinito: abilitato)",
"private-groups.warning": "Attenzione! Se questa opzione è disattivata e si hanno gruppi privati, questi diventano automaticamente pubblici.",
- "allow-multiple-badges": "Allow Multiple Badges",
+ "allow-multiple-badges": "Consenti più badge",
"allow-multiple-badges-help": "Questo flag può essere usato per consentire agli utenti di selezionare più badge di gruppo, richiede il supporto del tema.",
"max-name-length": "Lunghezza massima Nome Gruppo",
"max-title-length": "Lunghezza massima Titolo Gruppo",
diff --git a/public/language/it/admin/settings/guest.json b/public/language/it/admin/settings/guest.json
index f9aa27ef6d..16f90d7396 100644
--- a/public/language/it/admin/settings/guest.json
+++ b/public/language/it/admin/settings/guest.json
@@ -1,5 +1,5 @@
{
- "handles": "Gestione Ospite",
- "handles.enabled": "Consenti gestione ospiti",
+ "handles": "Nome utente Ospite",
+ "handles.enabled": "Consenti nome utente ospite",
"handles.enabled-help": "Questa opzione mostra un nuovo campo che permette agli ospiti di scegliere un nome da associare ad ogni post che fanno. Se disabilitata, saranno semplicemente chiamati \"Ospite\"."
}
\ No newline at end of file
diff --git a/public/language/it/admin/settings/tags.json b/public/language/it/admin/settings/tags.json
index 8059a66674..d2a2703e6c 100644
--- a/public/language/it/admin/settings/tags.json
+++ b/public/language/it/admin/settings/tags.json
@@ -1,6 +1,6 @@
{
"tag": "Impostazioni Tag",
- "link-to-manage": "Manage Tags",
+ "link-to-manage": "Gestisci tag",
"min-per-topic": "Tag minimi per discussione",
"max-per-topic": "Tag massimi per discussione",
"min-length": "Lunghezza minima tag",
diff --git a/public/language/it/admin/settings/user.json b/public/language/it/admin/settings/user.json
index 280c60fdcf..49118ffffc 100644
--- a/public/language/it/admin/settings/user.json
+++ b/public/language/it/admin/settings/user.json
@@ -9,7 +9,7 @@
"allow-login-with.email": "Solo Email",
"account-settings": "Impostazioni Account",
"gdpr_enabled": "Abilita la raccolta di consensi GDPR",
- "gdpr_enabled_help": "When enabled, all new registrants will be required to explicitly give consent for data collection and usage under the General Data Protection Regulation (GDPR). Note: Enabling GDPR does not force pre-existing users to provide consent. To do so, you will need to install the GDPR plugin.",
+ "gdpr_enabled_help": "Quando è abilitato, tutti i nuovi registranti dovranno dare il loro consenso esplicito per la raccolta e l'utilizzo dei dati ai sensi del regolamento generale sulla protezione dei dati (GDPR). Nota: L'abilitazione del GDPR non obbliga gli utenti preesistenti a fornire il consenso. Per farlo, è necessario installare il plugin GDPR.",
"disable-username-changes": "Disabilita il cambio dello username",
"disable-email-changes": "Disabilita il cambio di email",
"disable-password-changes": "Disabilita cambio password",
diff --git a/public/language/it/flags.json b/public/language/it/flags.json
index b70a4fb95c..a8c96d3235 100644
--- a/public/language/it/flags.json
+++ b/public/language/it/flags.json
@@ -32,7 +32,7 @@
"view-profile": "Vedi Profilo",
"start-new-chat": "Inizia Nuova Chat",
"go-to-target": "Visualizza oggetto segnalazione",
- "assign-to-me": "Assign To Me",
+ "assign-to-me": "Assegna a me",
"delete-post": "Elimina post",
"purge-post": "Elimina Post",
"restore-post": "Ripristina post",
@@ -45,7 +45,6 @@
"no-notes": "Nessuna nota condivisa",
"history": "Cronologia segnalazioni account",
- "back": "Torna all'elenco segnalazioni",
"no-history": "Nessuna cronologia segnalazione.",
"state-all": "Tutti gli stati",
diff --git a/public/language/it/global.json b/public/language/it/global.json
index c6f3e178bd..d75f15539d 100644
--- a/public/language/it/global.json
+++ b/public/language/it/global.json
@@ -30,7 +30,7 @@
"header.unread": "Non letti",
"header.tags": "Tag",
"header.popular": "Popolare",
- "header.top": "Top",
+ "header.top": "In alto",
"header.users": "Utenti",
"header.groups": "Gruppi",
"header.chats": "Chat",
@@ -54,7 +54,7 @@
"posts": "Post",
"best": "Migliore",
"votes": "Votazioni",
- "voters": "Voters",
+ "voters": "Votanti",
"upvoters": "Hanno votato positivamente",
"upvoted": "Apprezzati",
"downvoters": "Votata negativamente",
diff --git a/public/language/it/notifications.json b/public/language/it/notifications.json
index 92c1137f8f..97c0f1d94f 100644
--- a/public/language/it/notifications.json
+++ b/public/language/it/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Ci sono %1 richieste di registrazione che attendono di essere esaminate.",
"flag_assigned_to_you": "Segnalazione %1 ti è stata assegnata",
"post_awaiting_review": "Post in attesa di revisione",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Email Confermata",
"email-confirmed-message": "Grazie per aver validato la tua email. Il tuo account è ora completamente attivato.",
"email-confirm-error-message": "C'è stato un problema nella validazione del tuo indirizzo email. Potrebbe essere il codice non valido o scaduto.",
diff --git a/public/language/it/tags.json b/public/language/it/tags.json
index 6632d3ca71..dcdd2a3e23 100644
--- a/public/language/it/tags.json
+++ b/public/language/it/tags.json
@@ -4,5 +4,5 @@
"enter_tags_here": "Inserisci qui i tag, tra %1 e %2 caratteri ciascuno.",
"enter_tags_here_short": "Inserisci i tag...",
"no_tags": "Non ci sono ancora tag.",
- "select_tags": "Select Tags"
+ "select_tags": "Seleziona tag"
}
\ No newline at end of file
diff --git a/public/language/it/topic.json b/public/language/it/topic.json
index 06fbfa93d1..03d15e49cd 100644
--- a/public/language/it/topic.json
+++ b/public/language/it/topic.json
@@ -99,15 +99,15 @@
"fork_pid_count": "%1 post selezionati",
"fork_success": "Topic Diviso con successo ! Clicca qui per andare al Topic Diviso.",
"delete_posts_instruction": "Clicca sui post che vuoi eliminare/eliminare definitivamente",
- "merge_topics_instruction": "Click the topics you want to merge or search for them",
- "merge-topic-list-title": "List of topics to be merged",
- "merge-options": "Merge options",
- "merge-select-main-topic": "Select the main topic",
- "merge-new-title-for-topic": "New title for topic",
+ "merge_topics_instruction": "Clicca sulle discussioni che vuoi unire o cercare",
+ "merge-topic-list-title": "Elenco delle discussioni da unire",
+ "merge-options": "Opzioni di unione",
+ "merge-select-main-topic": "Seleziona discussione principale",
+ "merge-new-title-for-topic": "Nuovo titolo per la discussione",
"move_posts_instruction": "Clicca sui post che vuoi spostare",
"change_owner_instruction": "Clicca sui post che vuoi assegnare ad un altro utente",
"composer.title_placeholder": "Inserisci qui il titolo della discussione...",
- "composer.handle_placeholder": "Enter your name/handle here",
+ "composer.handle_placeholder": "Inserisci qui il tuo nome/nome utente ospite",
"composer.discard": "Annulla",
"composer.submit": "Invia",
"composer.replying_to": "Rispondendo a %1",
@@ -138,9 +138,9 @@
"diffs.no-revisions-description": "Questo post ha %1 revisioni.",
"diffs.current-revision": "revisione corrente",
"diffs.original-revision": "revisione originale",
- "diffs.restore": "Restore this revision",
- "diffs.restore-description": "A new revision will be appended to this post's edit history.",
- "diffs.post-restored": "Post successfully restored to earlier revision",
+ "diffs.restore": "Ripristina questa revisione",
+ "diffs.restore-description": "Una nuova revisione sarà aggiunta alla cronologia delle modifiche di questo post.",
+ "diffs.post-restored": "Post ripristinato con successo alla revisione precedente",
"timeago_later": "%1 successivo",
"timeago_earlier": "%1 precedente"
}
\ No newline at end of file
diff --git a/public/language/it/user.json b/public/language/it/user.json
index 723ad5e87d..6e6300c615 100644
--- a/public/language/it/user.json
+++ b/public/language/it/user.json
@@ -8,20 +8,20 @@
"email": "Email",
"confirm_email": "Conferma Email",
"account_info": "Informazioni dell'account",
- "admin_actions_label": "Administrative Actions",
+ "admin_actions_label": "Azioni amministrative",
"ban_account": "BAN dell'account",
"ban_account_confirm": "Sei sicuro di voler bannare questo utente?",
"unban_account": "Togli il BAN",
"delete_account": "Elimina Account",
- "delete_account_as_admin": "Delete Account",
- "delete_content": "Delete Account Content",
- "delete_all": "Delete Account and Content",
- "delete_account_confirm": "Are you sure you want to anonymize your posts and delete your account?
This action is irreversible and you will not be able to recover any of your data
Enter your password to confirm that you wish to destroy this account.",
- "delete_this_account_confirm": "Are you sure you want to delete this account while leaving its contents behind?
This action is irreversible, posts will be anonymized, and you will not be able to restore post associations with the deleted account
",
- "delete_account_content_confirm": "Are you sure you want to delete this account's content (posts/topics/uploads)?
This action is irreversible and you will not be able to recover any data
",
- "delete_all_confirm": "Are you sure you want to delete this account and all of its content (posts/topics/uploads)?
This action is irreversible and you will not be able to recover any data
",
+ "delete_account_as_admin": "Elimina account",
+ "delete_content": "Elimina contenuto account",
+ "delete_all": "Elimina account e contenuto",
+ "delete_account_confirm": "Sei sicuro di voler rendere anonimi i tuoi post ed eliminare il tuo account?\n
Questa azione è irreversibile e non sarà possibile recuperare nessuno dei tuoi dati
Inserisci la tua password per confermare che vuoi eliminare questo account.",
+ "delete_this_account_confirm": "Sei sicuro di voler eliminare questo account abbandonando il suo contenuto?
Questa azione è irreversibile, i post saranno resi anonimi e non sarà possibile ripristinare le associazioni dei post con l'account eliminato
",
+ "delete_account_content_confirm": "Sei sicuro di voler eliminare il contenuto di questo account (post/discussioni/upload)?
Questa azione è irreversibile e non sarà possibile recuperare i dati
",
+ "delete_all_confirm": "Sei sicuro di voler eliminare questo account e tutto il suo contenuto (post/discussioni/upload)?
Questa azione è irreversibile e non sarà possibile recuperare i dati
",
"account-deleted": "Account eliminato",
- "account-content-deleted": "Account content deleted",
+ "account-content-deleted": "Contenuto dell'account eliminato",
"fullname": "Nome e Cognome",
"website": "Sito Internet",
"location": "Località",
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "Hai i privilegi alla portabilità dei dati",
"consent.right_to_data_portability_description": "Puoi richiedere da noi un'esportazione leggibile meccanicamente di tutti i dati raccolti su di te e sul tuo account. Puoi farlo facendo clic sul pulsante appropriato in basso.",
"consent.export_profile": "Esporta profilo (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Esporta i contenuti caricati (.zip)",
- "consent.export_posts": "Esporta i post (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Esporta i post (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/ja/flags.json b/public/language/ja/flags.json
index 97ba818fbc..a46a36fc23 100644
--- a/public/language/ja/flags.json
+++ b/public/language/ja/flags.json
@@ -45,7 +45,6 @@
"no-notes": "共有ノートはありません。",
"history": "Account & Flag History",
- "back": "フラグリストに戻る",
"no-history": "フラグ履歴がありません",
"state-all": "全ての状態",
diff --git a/public/language/ja/notifications.json b/public/language/ja/notifications.json
index 9f95ab0c31..e3db188cd6 100644
--- a/public/language/ja/notifications.json
+++ b/public/language/ja/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "%1の登録リクエストがレビュー待ちです。",
"flag_assigned_to_you": "フラグ %1はあなたに割当てられました",
"post_awaiting_review": "レビュー待ちの投稿",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Eメールが確認されました",
"email-confirmed-message": "メールアドレス検証をして頂き、ありがとうございます。あなたのアカウントは完全にアクティブになりました。",
"email-confirm-error-message": "あなたのEメールアドレス検証に問題があります。コードが無効か、期限切れです。",
diff --git a/public/language/ja/user.json b/public/language/ja/user.json
index ab8b0ca267..209d5d920b 100644
--- a/public/language/ja/user.json
+++ b/public/language/ja/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "あなたはデータを移動する権利があります",
"consent.right_to_data_portability_description": "あなたは私たちにあなたとあなたのアカウントに関して収集されたデータの機械読み取り可能なエクスポートを要求することができます。 下の適切なボタンをクリックしてそれを行うことができます。",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "アップデートしたコンテンツをエクスポート(.zip)",
- "consent.export_posts": "投稿をエクスポート (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "投稿をエクスポート (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/ko/flags.json b/public/language/ko/flags.json
index 5f669b2624..16c51bf53f 100644
--- a/public/language/ko/flags.json
+++ b/public/language/ko/flags.json
@@ -45,7 +45,6 @@
"no-notes": "공유된 노트가 없습니다.",
"history": "Account & Flag History",
- "back": "신고 목록으로 돌아가기",
"no-history": "신고 기록들이 없습니다.",
"state-all": "모든 상태",
diff --git a/public/language/ko/notifications.json b/public/language/ko/notifications.json
index 930d3934ec..640ce1374a 100644
--- a/public/language/ko/notifications.json
+++ b/public/language/ko/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "%1 개의 회원가입 요청이 승인 대기중입니다.",
"flag_assigned_to_you": "신고 ID %1 이 나에게 배정되었습니다.",
"post_awaiting_review": "검토중인 게시물",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "이메일 인증 되었습니다",
"email-confirmed-message": "이메일을 인증해주셔서 감사합니다. 계정이 완전히 활성화되었습니다.",
"email-confirm-error-message": "이메일 주소를 인증하지 못했습니다. 코드가 올바르지 않거나 만료 되었을 수 있습니다.",
diff --git a/public/language/ko/user.json b/public/language/ko/user.json
index 77ca6830d8..bdaa5dc485 100644
--- a/public/language/ko/user.json
+++ b/public/language/ko/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "당신은 데이터 이동 권한이 있습니다.",
"consent.right_to_data_portability_description": "당신은 우리가 수집한 당신과 당신의 계정에 대한 어떠한 수집 데이터라도 기계가 읽을 수 있는 형태로 출력본을 요청할 수 있습니다. 아래에 적절한 버튼을 클릭하여 해당 처리를 수행할 수 있습니다.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "업로드한 콘텐츠 내보내기 (.zip)",
- "consent.export_posts": "포스트 내보내기 (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "포스트 내보내기 (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/lt/flags.json b/public/language/lt/flags.json
index 14801c4a6b..db16e34fbe 100644
--- a/public/language/lt/flags.json
+++ b/public/language/lt/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/lt/notifications.json b/public/language/lt/notifications.json
index e5310eb0dd..2b09fbc8ff 100644
--- a/public/language/lt/notifications.json
+++ b/public/language/lt/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "There are %1 registration requests awaiting review.",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "El. paštas patvirtintas",
"email-confirmed-message": "Dėkojame už el. pašto patvirtinimą. Jūsų paskyra pilnai aktyvuota.",
"email-confirm-error-message": "Įvyko klaida mėginant patvirtinti Jūsų el. pašto adresą. Galbūt kodas yra neteisingas, arba nebegalioajantis.",
diff --git a/public/language/lt/user.json b/public/language/lt/user.json
index 0568ca3b11..b3df88a37f 100644
--- a/public/language/lt/user.json
+++ b/public/language/lt/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "Turite teisę į duomenų perkėlimą",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/lv/flags.json b/public/language/lv/flags.json
index 8ed143eb7b..0d80cb2ac4 100644
--- a/public/language/lv/flags.json
+++ b/public/language/lv/flags.json
@@ -45,7 +45,6 @@
"no-notes": "Nav kopīgu piezīmju.",
"history": "Account & Flag History",
- "back": "Atpakaļ uz atzīmju sarakstu",
"no-history": "Nav atzīmju vēsture.",
"state-all": "Visi stāvokļi",
diff --git a/public/language/lv/notifications.json b/public/language/lv/notifications.json
index 2a929402a0..afd3c42343 100644
--- a/public/language/lv/notifications.json
+++ b/public/language/lv/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Ir %1 reģistrācijas pietiekumi, kas jāpārskata.",
"flag_assigned_to_you": "Atzīme %1 ir piešķirta Tev",
"post_awaiting_review": "Raksts, kas jāpārskata",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "E-pasta adrese ir apstiprināta",
"email-confirmed-message": "Paldies, ka apstiprināji e-pasta adresi. Tavs konts tagad ir pilnībā aktivizēts.",
"email-confirm-error-message": "Tavā e-pasta adreses apstiprināšanā radās problēma. Iespējams, kods ir nederīgs vai ir beidzies derīguma termiņš.",
diff --git a/public/language/lv/user.json b/public/language/lv/user.json
index 29514b5728..8a8792cb8f 100644
--- a/public/language/lv/user.json
+++ b/public/language/lv/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "Tev ir tiesības pārnest savus datus",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Eksportēt augšupielādēto saturu (.zip)",
- "consent.export_posts": "Eksportēt rakstus (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Eksportēt rakstus (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/ms/flags.json b/public/language/ms/flags.json
index b3561f9e38..fb8708fc16 100644
--- a/public/language/ms/flags.json
+++ b/public/language/ms/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/ms/notifications.json b/public/language/ms/notifications.json
index a6142f56b7..444e49c195 100644
--- a/public/language/ms/notifications.json
+++ b/public/language/ms/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Ada %1 permohonan ingin daftar yang sedang menunggu pengesahan.",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Emel Disahkan",
"email-confirmed-message": "Terima kasih kerana mengesahkan emel anda. Akaun anda telah diaktifkan sepenuhnya.",
"email-confirm-error-message": "Berlaku masalah semasa mengesahkan emel anda. Mungkin kod tidak sah atau tamat tempoh.",
diff --git a/public/language/ms/user.json b/public/language/ms/user.json
index 2435a2d8cb..dc2aee04c6 100644
--- a/public/language/ms/user.json
+++ b/public/language/ms/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/nb/flags.json b/public/language/nb/flags.json
index b3561f9e38..fb8708fc16 100644
--- a/public/language/nb/flags.json
+++ b/public/language/nb/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/nb/notifications.json b/public/language/nb/notifications.json
index 04d292395c..470d5d23bb 100644
--- a/public/language/nb/notifications.json
+++ b/public/language/nb/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "There are %1 registration requests awaiting review.",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "E-post bekreftet",
"email-confirmed-message": "Takk for at du har validert din e-post. Kontoen din er nå fullstendig aktivert.",
"email-confirm-error-message": "Det oppsto et problem under valdiering av din e-post. Koden kan ha vært ugyldig eller ha utløpt.",
diff --git a/public/language/nb/user.json b/public/language/nb/user.json
index 7bb2cc5e78..75ecea3615 100644
--- a/public/language/nb/user.json
+++ b/public/language/nb/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/nl/flags.json b/public/language/nl/flags.json
index a731bbc079..f9581c12af 100644
--- a/public/language/nl/flags.json
+++ b/public/language/nl/flags.json
@@ -45,7 +45,6 @@
"no-notes": "Geen gedeelde notities",
"history": "Account & markering geschiedenis",
- "back": "Terug naar Markeringen lijst",
"no-history": "Geen markering geschiedenis",
"state-all": "Alle statussen",
diff --git a/public/language/nl/notifications.json b/public/language/nl/notifications.json
index f0736ac8af..1b39924649 100644
--- a/public/language/nl/notifications.json
+++ b/public/language/nl/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Er is/zijn %1 registratieverzoek(en) die wacht(en) op goedkeuring.",
"flag_assigned_to_you": "Flag %1 is aan u toegewezen",
"post_awaiting_review": "Bericht wachtend op goedkeuring",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "E-mailadres bevestigd",
"email-confirmed-message": "Bedankt voor het bevestigen van je e-mailadres. Je account is nu volledig geactiveerd.",
"email-confirm-error-message": "Er was een probleem met het bevestigen van dit e-mailadres. Misschien is de code niet goed ingevoerd of was de beschikbare tijd inmiddels verstreken.",
diff --git a/public/language/nl/user.json b/public/language/nl/user.json
index ea179b12f0..004d513817 100644
--- a/public/language/nl/user.json
+++ b/public/language/nl/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "U hebt Recht op Dataportabiliteit",
"consent.right_to_data_portability_description": "U kan van ons machine-leesbare export opvragen van verzamelde gegevens van u en uw account. U kan dit doen door te klikken op de van toepassing zijnde knop hieronder.",
"consent.export_profile": "Exporteer profiel (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Exporteer geuploade inhoud (.zip)",
- "consent.export_posts": "Exporteer berichten (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Exporteer berichten (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/pl/flags.json b/public/language/pl/flags.json
index ea328fa88c..235e2b9ee6 100644
--- a/public/language/pl/flags.json
+++ b/public/language/pl/flags.json
@@ -45,7 +45,6 @@
"no-notes": "Brak udostępnionych notatek",
"history": "Konto i historia flag",
- "back": "Wróć do listy flag",
"no-history": "Brak historii flag",
"state-all": "Wszystkie stany",
diff --git a/public/language/pl/notifications.json b/public/language/pl/notifications.json
index a4de9c0506..768bb2b128 100644
--- a/public/language/pl/notifications.json
+++ b/public/language/pl/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "%1 żądania rejestracji oczekują na sprawdzenie.",
"flag_assigned_to_you": "Flaga %1 została przypisana do ciebie",
"post_awaiting_review": "Posty oczkujące na sprawdzenie",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "E-mail potwierdzony",
"email-confirmed-message": "Dziękujemy za potwierdzenie maila. Twoje konto zostało aktywowane.",
"email-confirm-error-message": "Wystąpił problem przy aktywacji - kod jest błędny lub przestarzały",
diff --git a/public/language/pl/user.json b/public/language/pl/user.json
index 9f506dde62..6d198605dd 100644
--- a/public/language/pl/user.json
+++ b/public/language/pl/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "Masz prawo do przenoszenia danych",
"consent.right_to_data_portability_description": "Możesz poprosić nas o eksport wszelkich danych gromadzonych na temat Ciebie i Twojego konta w formie do odczytu elektronicznego. W tym celu kliknij stosowny przycisk poniżej.",
"consent.export_profile": "Eksportuj profil (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Eksportuj przesłane treści (zip)",
- "consent.export_posts": "Eksportuj wpisy (csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Eksportuj wpisy (csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/pt-BR/flags.json b/public/language/pt-BR/flags.json
index 15ba843ad4..b0f346d44b 100644
--- a/public/language/pt-BR/flags.json
+++ b/public/language/pt-BR/flags.json
@@ -45,7 +45,6 @@
"no-notes": "Nenhuma nota compartilhada.",
"history": "Account & Flag History",
- "back": "Voltar à Lista de Sinaliações",
"no-history": "Sem histórico de sinalizações.",
"state-all": "Todos os estados",
diff --git a/public/language/pt-BR/notifications.json b/public/language/pt-BR/notifications.json
index 9a4df9b7b3..d9fc33c48a 100644
--- a/public/language/pt-BR/notifications.json
+++ b/public/language/pt-BR/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Há %1 pedidos de registro aguardando revisão.",
"flag_assigned_to_you": "A Sinalização %1 foi atribuída a você",
"post_awaiting_review": "Post aguardando revisão",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Email Confirmado",
"email-confirmed-message": "Obrigado por validar o seu email. Agora sua conta está plenamente ativada.",
"email-confirm-error-message": "Houve um problema ao validar o seu endereço de email. Talvez o código era invalido ou tenha expirado.",
diff --git a/public/language/pt-BR/user.json b/public/language/pt-BR/user.json
index 5a2548cb3d..510ab431d0 100644
--- a/public/language/pt-BR/user.json
+++ b/public/language/pt-BR/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "Você tem o Direito de Portabilidade de Dados",
"consent.right_to_data_portability_description": "Você pode solicitar de nós uma exportação legível por máquina de quaisquer dados coletados sobre você e sua conta. Você pode fazer isso clicando no botão apropriado abaixo.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Exportar Arquivos Enviados (.zip)",
- "consent.export_posts": "Exportar Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Exportar Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/pt-PT/flags.json b/public/language/pt-PT/flags.json
index 679c0f0017..0cc77c4493 100644
--- a/public/language/pt-PT/flags.json
+++ b/public/language/pt-PT/flags.json
@@ -45,7 +45,6 @@
"no-notes": "Não existem notas partilhadas.",
"history": "Conta & Histórico de Denúncias",
- "back": "Voltar para a Lista de Denúncias",
"no-history": "Não existe histórico de denúncias.",
"state-all": "Todos os estados",
diff --git a/public/language/pt-PT/notifications.json b/public/language/pt-PT/notifications.json
index bb0485dab5..ed1b911ef8 100644
--- a/public/language/pt-PT/notifications.json
+++ b/public/language/pt-PT/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Existem %1 pedidos de registro aguardando pela tua revisão.",
"flag_assigned_to_you": "A denúncia %1 foi atribuída a ti",
"post_awaiting_review": "Publicação a aguardar revisão",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "E-mail confirmado",
"email-confirmed-message": "Obrigado por validares o teu endereço de e-mail. A tua conta está agora totalmente ativa.",
"email-confirm-error-message": "Ocorreu um problema a validar o teu endereço de e-mail. Talvez o código seja inválido ou já tenha expirado.",
diff --git a/public/language/pt-PT/user.json b/public/language/pt-PT/user.json
index 72bedea683..8bf00ce733 100644
--- a/public/language/pt-PT/user.json
+++ b/public/language/pt-PT/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Exportar Perfil (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Exportar Arquivos Enviados (.zip)",
- "consent.export_posts": "Exportar Publicações (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Exportar Publicações (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/ro/flags.json b/public/language/ro/flags.json
index b3561f9e38..fb8708fc16 100644
--- a/public/language/ro/flags.json
+++ b/public/language/ro/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/ro/notifications.json b/public/language/ro/notifications.json
index 8de723abda..10008327aa 100644
--- a/public/language/ro/notifications.json
+++ b/public/language/ro/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "There are %1 registration requests awaiting review.",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Email confirmat",
"email-confirmed-message": "Îți mulțumim pentru validarea emailului. Contul tău este acuma activat.",
"email-confirm-error-message": "A fost o problemă cu activarea adresei tale de email. Poate codul de activare a fost invalid sau expirat.",
diff --git a/public/language/ro/user.json b/public/language/ro/user.json
index be47d536bc..4e87fdf5ff 100644
--- a/public/language/ro/user.json
+++ b/public/language/ro/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/ru/flags.json b/public/language/ru/flags.json
index 16ffca9bf6..42f916b635 100644
--- a/public/language/ru/flags.json
+++ b/public/language/ru/flags.json
@@ -45,7 +45,6 @@
"no-notes": "Нет примечаний.",
"history": "Account & Flag History",
- "back": "Вернуться к списку жалоб",
"no-history": "Нет истории жалобы.",
"state-all": "Все состояния",
diff --git a/public/language/ru/notifications.json b/public/language/ru/notifications.json
index 0da0fa4925..84322cf44e 100644
--- a/public/language/ru/notifications.json
+++ b/public/language/ru/notifications.json
@@ -35,7 +35,7 @@
"user_posted_to_dual": "Пользователи %1 и %2 ответили на сообщение в %3",
"user_posted_to_multiple": "%1 и %2 других пользователя ответили на сообщение в %3",
"user_posted_topic": "Пользователь %1 создал новую тему: %2",
- "user_edited_post": "%1 has edited a post in %2",
+ "user_edited_post": " %1 отредактировал сообщение в %2 ",
"user_started_following_you": "Пользователь %1 подписался на вас.",
"user_started_following_you_dual": "Пользователи %1 и %2 подписались на вас.",
"user_started_following_you_multiple": "%1 и %2 других пользователя подписались на вас.",
@@ -43,6 +43,9 @@
"new_register_multiple": "В очереди %1 заявок на регистрацию.",
"flag_assigned_to_you": "Жалоба %1 была назначена вам",
"post_awaiting_review": "Сообщение ожидает проверки",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Электронная почта подтверждена",
"email-confirmed-message": "Спасибо за подтверждение адреса электронной почты. Ваша учётная запись активирована.",
"email-confirm-error-message": "Ошибка проверки адреса электронной почты. Возможно, код подтверждения введён неправильно или у него истёк срок действия.",
@@ -54,7 +57,7 @@
"notificationType_upvote": "Когда кто-то проголосовал за ваше сообщение",
"notificationType_new-topic": "Когда кто-то, на кого вы подписаны, создаёт новую тему",
"notificationType_new-reply": "Когда в теме, за которой вы следите, появляется новое сообщение",
- "notificationType_post-edit": "When a post is edited in a topic you are watching",
+ "notificationType_post-edit": "Когда сообщение было отредактировано в теме, на которую вы подписаны",
"notificationType_follow": "Когда кто-то подписался на вас",
"notificationType_new-chat": "Когда вы получаете сообщение в чат",
"notificationType_group-invite": "Когда вы получаете приглашение в группу",
diff --git a/public/language/ru/user.json b/public/language/ru/user.json
index 730eceadf4..f4ae8693db 100644
--- a/public/language/ru/user.json
+++ b/public/language/ru/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "У вас есть право на перенос данных",
"consent.right_to_data_portability_description": "Вы можете запросить у нас машиночитаемый экспорт любых собранных данных о вас и вашей учетной записи. Вы можете сделать это, нажав соответствующую кнопку ниже.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Экспорт загруженного контента (.zip)",
- "consent.export_posts": "Экспорт сообщений (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Экспорт сообщений (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/rw/flags.json b/public/language/rw/flags.json
index b3561f9e38..fb8708fc16 100644
--- a/public/language/rw/flags.json
+++ b/public/language/rw/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/rw/notifications.json b/public/language/rw/notifications.json
index 44aa3a5231..466d7cef9d 100644
--- a/public/language/rw/notifications.json
+++ b/public/language/rw/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "There are %1 registration requests awaiting review.",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Email Yemejwe",
"email-confirmed-message": "Urakoze kugaragaza ko email yawe ikora. Ubu ngubu konte yawe irakora nta kabuza. ",
"email-confirm-error-message": "Havutse ikibazo mu gushaka kumenya niba email yawe ikora. Ushobora kuba wakoresheje kode itari yo cyangwa se yarengeje igihe. ",
diff --git a/public/language/rw/user.json b/public/language/rw/user.json
index 3bb81b7125..bbbdee232d 100644
--- a/public/language/rw/user.json
+++ b/public/language/rw/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/sc/flags.json b/public/language/sc/flags.json
index b3561f9e38..fb8708fc16 100644
--- a/public/language/sc/flags.json
+++ b/public/language/sc/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/sc/notifications.json b/public/language/sc/notifications.json
index ec509a66f6..e80a740a95 100644
--- a/public/language/sc/notifications.json
+++ b/public/language/sc/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "There are %1 registration requests awaiting review.",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Email Confirmed",
"email-confirmed-message": "Thank you for validating your email. Your account is now fully activated.",
"email-confirm-error-message": "There was a problem validating your email address. Perhaps the code was invalid or has expired.",
diff --git a/public/language/sc/user.json b/public/language/sc/user.json
index 753ab1c076..0412aafb39 100644
--- a/public/language/sc/user.json
+++ b/public/language/sc/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/sk/flags.json b/public/language/sk/flags.json
index d7369006b9..ef6b2e1d82 100644
--- a/public/language/sk/flags.json
+++ b/public/language/sk/flags.json
@@ -45,7 +45,6 @@
"no-notes": "Žiadne zdieľané poznámky.",
"history": "Account & Flag History",
- "back": "Späť do zoznamu príznakov",
"no-history": "Žiadna história príznakov.",
"state-all": "Všetky stavy",
diff --git a/public/language/sk/notifications.json b/public/language/sk/notifications.json
index e4a79d54ac..04d86ca116 100644
--- a/public/language/sk/notifications.json
+++ b/public/language/sk/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Nachádzajú sa %1 registrácie čakajúce na preskúmanie.",
"flag_assigned_to_you": "Príznak %1 vám bol priradený ",
"post_awaiting_review": "Príspevok na schválenie",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "E-mail bol potvrdený",
"email-confirmed-message": "Ďakujeme za potvrdenie Vášho e-mailu. Váš účet je teraz aktivovaný.",
"email-confirm-error-message": "Vyskytla sa chyba pri overení Vašej e-mailovej adresy. ",
diff --git a/public/language/sk/user.json b/public/language/sk/user.json
index f3889cbb36..f1726beafb 100644
--- a/public/language/sk/user.json
+++ b/public/language/sk/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "Máte právo na prenositeľnosť údajov ",
"consent.right_to_data_portability_description": "Môžete od nás požadovať strojovo čitateľné údaje, ktoré boli zozbierané o Vás a Vašom účte. Urobíte tak kliknutím na tlačidlá zobrazené nižšie.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Exportovať nahraný obsah (*.zip)",
- "consent.export_posts": "Exportovať príspevky (*.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Exportovať príspevky (*.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/sl/flags.json b/public/language/sl/flags.json
index b3561f9e38..fb8708fc16 100644
--- a/public/language/sl/flags.json
+++ b/public/language/sl/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/sl/notifications.json b/public/language/sl/notifications.json
index a352c5250d..418a4db93e 100644
--- a/public/language/sl/notifications.json
+++ b/public/language/sl/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Število registracijskih zahtev, ki čakajo na pregled: %1",
"flag_assigned_to_you": "Flag %1 has been assigned to you",
"post_awaiting_review": "Post awaiting review",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "E-poštni naslov potrjen",
"email-confirmed-message": "Hvala, da ste potrdili svoj e-naslov. Račun je sedaj aktiviran.",
"email-confirm-error-message": "Prišlo je do napake pri preverjanju vašega e-poštnega naslova. Morda je bila koda napačna ali pa je potekla.",
diff --git a/public/language/sl/user.json b/public/language/sl/user.json
index 6d4c52208c..5ed8f89452 100644
--- a/public/language/sl/user.json
+++ b/public/language/sl/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/sr/flags.json b/public/language/sr/flags.json
index 8a8f48aefb..cd00600691 100644
--- a/public/language/sr/flags.json
+++ b/public/language/sr/flags.json
@@ -27,7 +27,7 @@
"filter-cid-all": "Све категорије",
"apply-filters": "Примени филтере",
- "quick-actions": "Quick Actions",
+ "quick-actions": "Брзе радње",
"flagged-user": "Означени корисник",
"view-profile": "Погледај профил",
"start-new-chat": "Започни ново ћаскање",
@@ -45,7 +45,6 @@
"no-notes": "Нема дељених бележака.",
"history": "Account & Flag History",
- "back": "Назад на списак заставица",
"no-history": "Нема историје заставица",
"state-all": "Сва стања",
diff --git a/public/language/sr/notifications.json b/public/language/sr/notifications.json
index 5f3cfd6e66..00c4a8c875 100644
--- a/public/language/sr/notifications.json
+++ b/public/language/sr/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Постоје %1 захтева за регистрацију који чекају преглед.",
"flag_assigned_to_you": "Заставица %1 је додељена вама",
"post_awaiting_review": "Порука на чекању за преглед",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Е-пошта је потврђена.",
"email-confirmed-message": "Хвала на овери ваше е-поште. Ваш налог је сада у потпуности активан.",
"email-confirm-error-message": "Дошло је до проблема са овером ваше е-поште. Можда је код неисправан или је истекао.",
diff --git a/public/language/sr/tags.json b/public/language/sr/tags.json
index f65e4aacdc..fb7273af58 100644
--- a/public/language/sr/tags.json
+++ b/public/language/sr/tags.json
@@ -4,5 +4,5 @@
"enter_tags_here": "Овде унесите ознаке, од %1 до %2 знакова за сваку.",
"enter_tags_here_short": "Унесите ознаке...",
"no_tags": "Још увек нема ознака.",
- "select_tags": "Select Tags"
+ "select_tags": "Изабери ознаке"
}
\ No newline at end of file
diff --git a/public/language/sr/topic.json b/public/language/sr/topic.json
index 42afa2fd29..6a07ef3a4e 100644
--- a/public/language/sr/topic.json
+++ b/public/language/sr/topic.json
@@ -99,11 +99,11 @@
"fork_pid_count": "Одабрано порука: %1",
"fork_success": "Тема је успешно рачвана! Кликните овде за одлазак на рачвану тему.",
"delete_posts_instruction": "Кликните на поруке које желите да избришете/очистите",
- "merge_topics_instruction": "Click the topics you want to merge or search for them",
- "merge-topic-list-title": "List of topics to be merged",
- "merge-options": "Merge options",
- "merge-select-main-topic": "Select the main topic",
- "merge-new-title-for-topic": "New title for topic",
+ "merge_topics_instruction": "Кликните на теме које желите да спојите или претражите",
+ "merge-topic-list-title": "Списак тема за спајање",
+ "merge-options": "Опције спајања",
+ "merge-select-main-topic": "Изаберите главну тему",
+ "merge-new-title-for-topic": "Нови наслов теме",
"move_posts_instruction": "Кликните на поруке које желите да преместите",
"change_owner_instruction": "Кликните на поруке које желите да доделите другом кориснику",
"composer.title_placeholder": "Овде унесите назив теме...",
@@ -138,9 +138,9 @@
"diffs.no-revisions-description": "Ова порука има %1 корекција.",
"diffs.current-revision": "тренутна корекција",
"diffs.original-revision": "оригинална корекција",
- "diffs.restore": "Restore this revision",
- "diffs.restore-description": "A new revision will be appended to this post's edit history.",
- "diffs.post-restored": "Post successfully restored to earlier revision",
+ "diffs.restore": "Врати корекцију",
+ "diffs.restore-description": "Нова корекција биће додата историји уређивања ове поруке.",
+ "diffs.post-restored": "Порука је успешно враћена на ранију корекцију",
"timeago_later": "%1 касније",
"timeago_earlier": "%1 раније"
}
\ No newline at end of file
diff --git a/public/language/sr/user.json b/public/language/sr/user.json
index b4018d31c9..6b750c16f1 100644
--- a/public/language/sr/user.json
+++ b/public/language/sr/user.json
@@ -8,20 +8,20 @@
"email": "Е-пошта",
"confirm_email": "Потврда е-поште",
"account_info": "Информације о налогу",
- "admin_actions_label": "Administrative Actions",
+ "admin_actions_label": "Административне радње",
"ban_account": "Забрани налог",
"ban_account_confirm": "Да ли заиста желите да забраните овог корисника?",
"unban_account": "Скини забрану налогу",
"delete_account": "Брисање налога",
- "delete_account_as_admin": "Delete Account",
- "delete_content": "Delete Account Content",
- "delete_all": "Delete Account and Content",
+ "delete_account_as_admin": "Избриши налог",
+ "delete_content": "Избриши садржај налога",
+ "delete_all": "Избриши налог и садржај",
"delete_account_confirm": "Are you sure you want to anonymize your posts and delete your account?
This action is irreversible and you will not be able to recover any of your data
Enter your password to confirm that you wish to destroy this account.",
"delete_this_account_confirm": "Are you sure you want to delete this account while leaving its contents behind?
This action is irreversible, posts will be anonymized, and you will not be able to restore post associations with the deleted account
",
"delete_account_content_confirm": "Are you sure you want to delete this account's content (posts/topics/uploads)?
This action is irreversible and you will not be able to recover any data
",
"delete_all_confirm": "Are you sure you want to delete this account and all of its content (posts/topics/uploads)?
This action is irreversible and you will not be able to recover any data
",
"account-deleted": "Налог је избрисан",
- "account-content-deleted": "Account content deleted",
+ "account-content-deleted": "Садржај налога је избрисан",
"fullname": "Пуно име",
"website": "Веб сајт",
"location": "Локација",
@@ -151,7 +151,7 @@
"info.ban-history": "Историја недавно забрањених налога",
"info.no-ban-history": "Овај корисник никада није био забрањен",
"info.banned-until": "Забрањен до %1",
- "info.banned-expiry": "Expiry",
+ "info.banned-expiry": "Истиче",
"info.banned-permanently": "Забрањен трајно",
"info.banned-reason-label": "Разлог",
"info.banned-no-reason": "Није дат разлог.",
@@ -178,7 +178,10 @@
"consent.right_to_erasure_description": "У било које време, у могућности сте да опозовете вашу сагласност за прикупљање и/или обраду података брисањем вашег налога. Ваш појединачни профил може бити избрисан, иако ће ваш објављени садржај остати. Ако желите да избришете и свој налог и садржај, молимо контактирајте администрацију овог веб сајта.",
"consent.right_to_data_portability": "Имате право на преносивост података",
"consent.right_to_data_portability_description": "Можете тражити од нас машински читљив извоз прикупљених података о вама и вашем налогу. То можете урадити кликом на одговарајуће дугме испод.",
- "consent.export_profile": "Export Profile (.json)",
+ "consent.export_profile": "Извези профил (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Извези отпремљени садржај (.zip)",
- "consent.export_posts": "Извези поруке (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Извези поруке (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/sv/flags.json b/public/language/sv/flags.json
index 4c2f786fbe..64e67aff4c 100644
--- a/public/language/sv/flags.json
+++ b/public/language/sv/flags.json
@@ -45,7 +45,6 @@
"no-notes": "Inga delade anteckningar.",
"history": "Account & Flag History",
- "back": "Tillbaks till flagglista",
"no-history": "Ingen flagghitorik.",
"state-all": "Alla status",
diff --git a/public/language/sv/notifications.json b/public/language/sv/notifications.json
index a77f77ed77..500602ade4 100644
--- a/public/language/sv/notifications.json
+++ b/public/language/sv/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Det finns %1 förfrågningar om registrering som inväntar granskning.",
"flag_assigned_to_you": "Flaggan %1 har tillskrivits dig",
"post_awaiting_review": "Inlägg väntar på granskning",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "E-post bekräftad",
"email-confirmed-message": "Tack för att du bekräftat din e-postadress. Ditt konto är nu fullt ut aktiverat.",
"email-confirm-error-message": "Det uppstod ett problem med bekräftelsen av din e-postadress. Kanske var koden felaktig eller ogiltig.",
diff --git a/public/language/sv/user.json b/public/language/sv/user.json
index 8c6aa824c3..15dcccdaf5 100644
--- a/public/language/sv/user.json
+++ b/public/language/sv/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "Du har rätten till dataförflyttbarhet",
"consent.right_to_data_portability_description": "Du kan hämta en maskinläslig export av all insamlad data om dig och ditt konto. Du kan göra det genom att klicka på passande knapp nedan.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Exportera uppladdat innehåll (.zip)",
- "consent.export_posts": "Exportera poster (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Exportera poster (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/th/flags.json b/public/language/th/flags.json
index 015580f4bd..1c75c2da4f 100644
--- a/public/language/th/flags.json
+++ b/public/language/th/flags.json
@@ -45,7 +45,6 @@
"no-notes": "ไม่มีโน้ตที่แชร์",
"history": "Account & Flag History",
- "back": "กลับไปยังรายการปักธง",
"no-history": "ไม่มีประวัติปักธง",
"state-all": "สถานะทั้งหมด",
diff --git a/public/language/th/notifications.json b/public/language/th/notifications.json
index 0bc2009f3d..5d8b12583e 100644
--- a/public/language/th/notifications.json
+++ b/public/language/th/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "มี%1คำขอสมัครสมาชิกที่รอการรีวิว",
"flag_assigned_to_you": "ปักธง %1ได้ถูกปักธงให้คุณ",
"post_awaiting_review": "โพสกำลังรอการพิจารณา",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Email ได้รับการยืนยันแล้ว",
"email-confirmed-message": "ขอบคุณที่ยืนยัน Email ของคุณ บัญชีของคุณสามารถใช้งานได้แล้ว",
"email-confirm-error-message": "มีปัญหาในการยืนยัน Email ของคุณ บางทีรหัสไม่ถูกต้องหรือหมดอายุแล้ว",
diff --git a/public/language/th/user.json b/public/language/th/user.json
index 1f45460d28..1978f1651c 100644
--- a/public/language/th/user.json
+++ b/public/language/th/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "You have the Right to Data Portability",
"consent.right_to_data_portability_description": "You may request from us a machine-readable export of any collected data about you and your account. You can do so by clicking the appropriate button below.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Export Uploaded Content (.zip)",
- "consent.export_posts": "Export Posts (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Export Posts (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/tr/admin/manage/users.json b/public/language/tr/admin/manage/users.json
index 6f7290c784..b9515a392b 100644
--- a/public/language/tr/admin/manage/users.json
+++ b/public/language/tr/admin/manage/users.json
@@ -94,11 +94,11 @@
"alerts.validate-email-success": "E-postalar doğrulandı",
"alerts.validate-force-password-reset-success": "Kullanıcıların şifreleri sıfırlandı ve mevcut oturumları iptal edildi. ",
"alerts.password-reset-confirm": "Bu kullanıcıya(lara) şifre sıfırlama e-postası(ları) göndermek istiyor musunuz?",
- "alerts.confirm-delete": "Warning!Do you really want to delete user(s)?
This action is not reversible! Only the user account will be deleted, their posts and topics will remain.
",
+ "alerts.confirm-delete": "Uyarı!Kullanıcı(lar)ı gerçekten silmek istiyor musunuz?
Bu işlem geri alınamaz! Yalnızca kullanıcı hesapları silinecektir, iletiler ve konular kalacaktır.",
"alerts.delete-success": "Kullanıcı(lar) Silindi!",
- "alerts.confirm-delete-content": "Warning!
Do you really want to delete these user(s) content?
This action is not reversible! The users' accounts will remain, but their posts and topics will be deleted.
",
- "alerts.delete-content-success": "User(s) Content Deleted!",
- "alerts.confirm-purge": "Warning!Do you really want to delete user(s) and their content?
This action is not reversible! All user data and content will be erased!
",
+ "alerts.confirm-delete-content": "Uyarı!Bu kullanıcının(ların) içeriklerinigerçekten silmek istiyor musunuz?
Bu işlem geri alınamaz! Yalnızca kullanıcı hesabı kalacaktır, iletiler ve konular silinecektir.
",
+ "alerts.delete-content-success": "Kullanıcının(ların) İçerikleri Silindi!",
+ "alerts.confirm-purge": "Uyarı!Kullanıcı(ları) ve içeriklerini silmeyi gerçekten istiyor musunuz?
Bu işlem geri alınamaz! Tüm kullanıcı verileri ve içerikleri silinecektir.
",
"alerts.create": "Kullanıcı Oluştur",
"alerts.button-create": "Oluştur",
"alerts.button-cancel": "İptal",
diff --git a/public/language/tr/flags.json b/public/language/tr/flags.json
index e9f912b448..7b71d0f76b 100644
--- a/public/language/tr/flags.json
+++ b/public/language/tr/flags.json
@@ -32,7 +32,7 @@
"view-profile": "Profili Gör",
"start-new-chat": "Yeni Sohbet Başlat",
"go-to-target": "Şikayet Edilen İçeriği Gör",
- "assign-to-me": "Assign To Me",
+ "assign-to-me": "Kendime ata",
"delete-post": "İletiyi Sil",
"purge-post": "İletiyi Temizle",
"restore-post": "İletiyi Geri Getir",
@@ -45,7 +45,6 @@
"no-notes": "Not paylaşılmadı",
"history": "Hesap & Şikayet Geçmişi",
- "back": "Şikayet Listesine Geri Dön",
"no-history": "Şikayet geçmişi yok",
"state-all": "Bütün Bildiriler",
diff --git a/public/language/tr/notifications.json b/public/language/tr/notifications.json
index 00df398ac0..329d826db7 100644
--- a/public/language/tr/notifications.json
+++ b/public/language/tr/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Beklemede %1 kayıt olma isteği bulunmaktadır.",
"flag_assigned_to_you": "Şikayet %1 size devredildi",
"post_awaiting_review": "İnceleme bekleyen ileti(ler) var",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "E-posta onaylandı",
"email-confirmed-message": "E-postanızı onayladığınız için teşekkürler. Hesabınız tamamen aktif edildi.",
"email-confirm-error-message": "E-posta adresinizi onaylarken bir hata oluştu. Kodunuz geçersiz ya da eski olabilir.",
diff --git a/public/language/tr/topic.json b/public/language/tr/topic.json
index 5bd05fa39b..4b8e572ed8 100644
--- a/public/language/tr/topic.json
+++ b/public/language/tr/topic.json
@@ -138,9 +138,9 @@
"diffs.no-revisions-description": "Bu iletinin %1 revizyonu var.",
"diffs.current-revision": "mevcut revizyon",
"diffs.original-revision": "orijinal revizyon",
- "diffs.restore": "Restore this revision",
- "diffs.restore-description": "A new revision will be appended to this post's edit history.",
- "diffs.post-restored": "Post successfully restored to earlier revision",
+ "diffs.restore": "Bu revizyonu geri getir",
+ "diffs.restore-description": "Yeni bir revizyon bu iletinın geçmişine eklenecek. ",
+ "diffs.post-restored": "İleti önceki revizyona başarıyla geri getirildi",
"timeago_later": "%1 sonra",
"timeago_earlier": "%1 önce"
}
\ No newline at end of file
diff --git a/public/language/tr/user.json b/public/language/tr/user.json
index 3fd8ed0c8d..e1a8f4613b 100644
--- a/public/language/tr/user.json
+++ b/public/language/tr/user.json
@@ -8,7 +8,7 @@
"email": "E-posta",
"confirm_email": "E-posta Adresini Onayla",
"account_info": "Hesap Bilgisi",
- "admin_actions_label": "Administrative Actions",
+ "admin_actions_label": "Yönetim Aktiviteleri",
"ban_account": "Hesabı Yasakla",
"ban_account_confirm": "Hesabı yasaklamak istediğinizden emin misiniz?",
"unban_account": "Hesabın Yasağını Kaldır",
@@ -16,10 +16,10 @@
"delete_account_as_admin": "Hesabı Sil",
"delete_content": "Hesabın İçeriğini Sil",
"delete_all": "Hesabı ve İçeriğini Sil",
- "delete_account_confirm": "Are you sure you want to anonymize your posts and delete your account?
This action is irreversible and you will not be able to recover any of your data
Enter your password to confirm that you wish to destroy this account.",
- "delete_this_account_confirm": "Are you sure you want to delete this account while leaving its contents behind?
This action is irreversible, posts will be anonymized, and you will not be able to restore post associations with the deleted account
",
- "delete_account_content_confirm": "Are you sure you want to delete this account's content (posts/topics/uploads)?
This action is irreversible and you will not be able to recover any data
",
- "delete_all_confirm": "Are you sure you want to delete this account and all of its content (posts/topics/uploads)?
This action is irreversible and you will not be able to recover any data
",
+ "delete_account_confirm": "Hesabınızı silip iletilerinizi anonimleştirmek istediğinize emin misiniz?
Bu işlem geri döndürülemez ve verilerinizin herhangi bir bölümünü kurtaramazsınız
Bu hesabı yoketme isteğinizi onaylamak için şifrenizi girin.",
+ "delete_this_account_confirm": "Hesabınızı silip, içeriğini geride bırakmak istediğinize emin misiniz?
Bu işlem geri döndürülemez, iletiler anonimleşecek ve verilerinizi geri getiremeceksiniz
",
+ "delete_account_content_confirm": "Hesabınızın içeriğini silmek istediğinize emin misiniz (iletiler/başlıklar/yüklemeler)?
Bu işlem geri döndürülemez, hiçbir veriyi geri getiremeceksiniz
",
+ "delete_all_confirm": "Hesabınızı ve tüm içeriğini silmek istediğinize emin misiniz (iletiler/başlıklar/yüklemeler)?
Bu işlem geri döndürülemez, hiçbir veriyi geri getiremeceksiniz
",
"account-deleted": "Hesap silindi",
"account-content-deleted": "Hesaba ait içerik silindi",
"fullname": "İsim Soyisim",
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "Veri taşıma hakkına sahipsiniz",
"consent.right_to_data_portability_description": "Sizden ve hesabınız hakkında toplanan verilere makine tarafından okunabilir bir veri talep edebilirsiniz. Aşağıdaki uygun düğmeyi tıklayarak bunu yapabilirsiniz.",
"consent.export_profile": "Profili Dışa Aktar (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Karşıya Yüklenmiş İçeriği Dışarı Aktar (.zip)",
- "consent.export_posts": "Gönderileri Dışa Aktar (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Gönderileri Dışa Aktar (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/uk/notifications.json b/public/language/uk/notifications.json
index 05f0a1d99f..eef2ab42a1 100644
--- a/public/language/uk/notifications.json
+++ b/public/language/uk/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "%1 запити на реєстрацію очікують розгляду.",
"flag_assigned_to_you": "На вас була подана скарга %1",
"post_awaiting_review": "Пост очікує на перевірку",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Електронну пошту підтверджено",
"email-confirmed-message": "Дякуємо за підтвердження електронної пошти. Ваш акаунт тепер повністю активовано.",
"email-confirm-error-message": "При перевірці вашої електронної пошти сталася проблема. Можливо код був недійсним або простроченим.",
diff --git a/public/language/uk/user.json b/public/language/uk/user.json
index 283f900dbd..2a388cbc00 100644
--- a/public/language/uk/user.json
+++ b/public/language/uk/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "У вас є Право на Переносимість Даних",
"consent.right_to_data_portability_description": "Ви можете отримати від нас експортовану копію машинно-читабельних даних, які були зібрані про вас і ваш акаунт. Ви можете це зробити, натиснувши на відповідну кнопку внизу.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Експортувати Завантажений Контент (.zip)",
- "consent.export_posts": "Експортувати Пости (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Експортувати Пости (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/vi/flags.json b/public/language/vi/flags.json
index b3561f9e38..fb8708fc16 100644
--- a/public/language/vi/flags.json
+++ b/public/language/vi/flags.json
@@ -45,7 +45,6 @@
"no-notes": "No shared notes.",
"history": "Account & Flag History",
- "back": "Back to Flags List",
"no-history": "No flag history.",
"state-all": "All states",
diff --git a/public/language/vi/notifications.json b/public/language/vi/notifications.json
index 90dd6b3a4a..cbc6e98906 100644
--- a/public/language/vi/notifications.json
+++ b/public/language/vi/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "Có %1 đơn đăng ký đang chờ xem xét.",
"flag_assigned_to_you": "Cảnh báo %1 đã được ghi nhận đối với bạn",
"post_awaiting_review": "Bài đăng đang chờ xét duyệt",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "Đã xác nhận email",
"email-confirmed-message": "Cảm ơn bạn đã xác nhận địa chỉ email của bạn. Tài khoản của bạn đã được kích hoạt đầy đủ.",
"email-confirm-error-message": "Đã có lỗi khi xác nhận địa chỉ email. Có thể đoạn mã không đúng hoặc đã hết hạn.",
diff --git a/public/language/vi/user.json b/public/language/vi/user.json
index fe58858753..9d29bc2adc 100644
--- a/public/language/vi/user.json
+++ b/public/language/vi/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "Bạn có quyền di chuyển dữ liệu",
"consent.right_to_data_portability_description": "Bạn có thể yêu cầu chúng tôi xuất khẩu có thể đọc được bằng máy đối với bất kỳ dữ liệu được thu thập nào về bạn và tài khoản của bạn. Bạn có thể làm như vậy bằng cách nhấp vào nút thích hợp bên dưới.",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "Xuất nội dung đã tải lên (.zip)",
- "consent.export_posts": "Xuất bài viết (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "Xuất bài viết (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/zh-CN/flags.json b/public/language/zh-CN/flags.json
index 2a58d70cb4..5daa8ab4bf 100644
--- a/public/language/zh-CN/flags.json
+++ b/public/language/zh-CN/flags.json
@@ -45,7 +45,6 @@
"no-notes": "没有共享的备注内容。",
"history": "Account & Flag History",
- "back": "返回举报列表",
"no-history": "没有举报历史。",
"state-all": "所有状态",
diff --git a/public/language/zh-CN/notifications.json b/public/language/zh-CN/notifications.json
index bb1568511c..e45009c928 100644
--- a/public/language/zh-CN/notifications.json
+++ b/public/language/zh-CN/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "有 %1 条注册申请等待批准。",
"flag_assigned_to_you": "举报 %1 已经被指派给您",
"post_awaiting_review": "请求查验帖子",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "电子邮箱已确认",
"email-confirmed-message": "感谢您验证您的电子邮箱。您的帐户现已完全激活。",
"email-confirm-error-message": "验证的您电子邮箱地址时出现了问题。可能是因为验证码无效或已过期。",
diff --git a/public/language/zh-CN/user.json b/public/language/zh-CN/user.json
index 7bf6f52d78..4fd74dd99f 100644
--- a/public/language/zh-CN/user.json
+++ b/public/language/zh-CN/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "您拥有数据转移权",
"consent.right_to_data_portability_description": "您也许想导出有关您和您的账号的机器可读副本。您可以点击下方的按钮来获取它们。",
"consent.export_profile": "Export Profile (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "导出上传文件 (.zip)",
- "consent.export_posts": "导出帖子 (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "导出帖子 (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/language/zh-TW/flags.json b/public/language/zh-TW/flags.json
index 2d9dfe4f51..21f84dfbea 100644
--- a/public/language/zh-TW/flags.json
+++ b/public/language/zh-TW/flags.json
@@ -45,7 +45,6 @@
"no-notes": "沒有共享的備註內容。",
"history": "帳戶 & 舉報紀錄",
- "back": "返回舉報列表",
"no-history": "沒有舉報歷史。",
"state-all": "所有狀態",
diff --git a/public/language/zh-TW/notifications.json b/public/language/zh-TW/notifications.json
index 9e346e2a6f..129454c339 100644
--- a/public/language/zh-TW/notifications.json
+++ b/public/language/zh-TW/notifications.json
@@ -43,6 +43,9 @@
"new_register_multiple": "有 %1 個註冊申請等待批准。",
"flag_assigned_to_you": "舉報 %1 已經被指派給您",
"post_awaiting_review": "請求查驗貼文",
+ "profile-exported": "%1 profile exported, click to download",
+ "posts-exported": "%1 posts exported, click to download",
+ "uploads-exported": "%1 uploads exported, click to download",
"email-confirmed": "電子信箱已確認",
"email-confirmed-message": "感謝您驗證您的電子信箱。您的帳戶現已完全啟用。",
"email-confirm-error-message": "驗證的您電子信箱地址時出現了問題。可能是因為驗證碼無效或已過期。",
diff --git a/public/language/zh-TW/user.json b/public/language/zh-TW/user.json
index fb68557d0d..40bb490cae 100644
--- a/public/language/zh-TW/user.json
+++ b/public/language/zh-TW/user.json
@@ -179,6 +179,9 @@
"consent.right_to_data_portability": "您擁有資料轉移權",
"consent.right_to_data_portability_description": "您也許想導出有關您和您的帳戶的機器可讀副本。您可以點擊下方的按鈕來獲取它們。",
"consent.export_profile": "輸出個人資料 (.json)",
+ "consent.export-profile-success": "Exporting profile, you will get a notification when it is complete.",
"consent.export_uploads": "導出上傳檔案 (.zip)",
- "consent.export_posts": "導出貼文 (.csv)"
+ "consent.export-uploads-success": "Exporting uploads, you will get a notification when it is complete.",
+ "consent.export_posts": "導出貼文 (.csv)",
+ "consent.export-posts-success": "Exporting posts, you will get a notification when it is complete."
}
\ No newline at end of file
diff --git a/public/openapi/read.yaml b/public/openapi/read.yaml
index 87c4ce5bb4..11d072ed54 100644
--- a/public/openapi/read.yaml
+++ b/public/openapi/read.yaml
@@ -2941,7 +2941,7 @@ paths:
get:
tags:
- users
- summary: Export a user's profile data (.csv)
+ summary: Export a user's profile data (.json)
parameters:
- name: userslug
in: path
@@ -2951,9 +2951,9 @@ paths:
example: admin
responses:
"200":
- description: "A CSV file containing the user profile"
+ description: "A JSON file containing the user profile"
content:
- text/csv:
+ text/json:
schema:
type: string
format: binary
@@ -7636,29 +7636,14 @@ paths:
items:
type: object
properties:
- type:
- type: string
bodyShort:
type: string
- bodyLong:
- type: string
- pid:
- oneOf:
- - type: number
- - type: string
- tid:
- type: number
- description: A topic identifier
path:
type: string
nid:
type: string
from:
type: number
- mergeId:
- type: string
- topicTitle:
- type: string
importance:
type: number
datetime:
@@ -7677,6 +7662,7 @@ paths:
removed, etc.)
picture:
type: string
+ nullable: true
uid:
type: number
description: A user identifier
@@ -7694,12 +7680,11 @@ paths:
example: "#f44336"
image:
type: string
+ nullable: true
read:
type: boolean
readClass:
type: string
- subject:
- type: string
filters:
type: array
items:
diff --git a/public/src/client/account/consent.js b/public/src/client/account/consent.js
index f038c7acea..f53bc365b0 100644
--- a/public/src/client/account/consent.js
+++ b/public/src/client/account/consent.js
@@ -16,6 +16,21 @@ define('forum/account/consent', ['forum/account/header'], function (header) {
ajaxify.refresh();
});
});
+
+ handleExport($('[data-action="export-profile"]'), 'user.exportProfile', '[[user:consent.export-profile-success]]');
+ handleExport($('[data-action="export-posts"]'), 'user.exportPosts', '[[user:consent.export-posts-success]]');
+ handleExport($('[data-action="export-uploads"]'), 'user.exportUploads', '[[user:consent.export-uploads-success]]');
+
+ function handleExport(el, method, success) {
+ el.on('click', function () {
+ socket.emit(method, { uid: ajaxify.data.uid }, function (err) {
+ if (err) {
+ return app.alertError(err.message);
+ }
+ app.alertSuccess(success);
+ });
+ });
+ }
};
return Consent;
diff --git a/public/src/client/account/edit.js b/public/src/client/account/edit.js
index a546c71e6f..c6f99d733b 100644
--- a/public/src/client/account/edit.js
+++ b/public/src/client/account/edit.js
@@ -228,7 +228,6 @@ define('forum/account/edit', ['forum/account/header', 'translator', 'components'
pictureCropper.show({
socketMethod: 'user.uploadCroppedPicture',
- route: config.relative_path + '/api/user/' + ajaxify.data.userslug + '/uploadpicture',
aspectRatio: 1 / 1,
paramName: 'uid',
paramValue: ajaxify.data.theirid,
diff --git a/public/src/client/account/header.js b/public/src/client/account/header.js
index ac4549610e..917d5b8791 100644
--- a/public/src/client/account/header.js
+++ b/public/src/client/account/header.js
@@ -50,7 +50,9 @@ define('forum/account/header', [
});
- components.get('account/ban').on('click', banAccount);
+ components.get('account/ban').on('click', function () {
+ banAccount(ajaxify.data.theirid);
+ });
components.get('account/unban').on('click', unbanAccount);
components.get('account/delete-account').on('click', handleDeleteEvent.bind(null, 'account'));
components.get('account/delete-content').on('click', handleDeleteEvent.bind(null, 'content'));
diff --git a/public/src/client/topic/images.js b/public/src/client/topic/images.js
index 3be0303e43..c1dc5866db 100644
--- a/public/src/client/topic/images.js
+++ b/public/src/client/topic/images.js
@@ -25,7 +25,7 @@ define('forum/topic/images', [], function () {
if (!$this.parent().is('a')) {
$this.wrap('');
+ ' target="_blank" rel="noopener">');
}
});
};
diff --git a/src/analytics.js b/src/analytics.js
index 3db38cba27..dcc9c2ac9d 100644
--- a/src/analytics.js
+++ b/src/analytics.js
@@ -138,7 +138,7 @@ Analytics.writeData = async function () {
try {
await Promise.all(dbQueue);
} catch (err) {
- winston.error('[analytics] Encountered error while writing analytics to data store', err);
+ winston.error('[analytics] Encountered error while writing analytics to data store', err.stack);
throw err;
}
};
diff --git a/src/categories/data.js b/src/categories/data.js
index 55052801d2..47b4a9e2b9 100644
--- a/src/categories/data.js
+++ b/src/categories/data.js
@@ -14,13 +14,9 @@ module.exports = function (Categories) {
if (!Array.isArray(cids) || !cids.length) {
return [];
}
- let categories;
+
const keys = cids.map(cid => 'category:' + cid);
- if (fields.length) {
- categories = await db.getObjectsFields(keys, fields);
- } else {
- categories = await db.getObjects(keys);
- }
+ const categories = await (fields.length ? db.getObjectsFields(keys, fields) : db.getObjects(keys));
categories.forEach(category => modifyCategory(category, fields));
return categories;
};
diff --git a/src/cli/manage.js b/src/cli/manage.js
index 3eeb0d0686..de250ce4aa 100644
--- a/src/cli/manage.js
+++ b/src/cli/manage.js
@@ -85,7 +85,7 @@ function activate(plugin) {
},
], function (err) {
if (err) {
- winston.error('An error occurred during plugin activation', err);
+ winston.error('An error occurred during plugin activation', err.stack);
throw err;
}
process.exit(0);
@@ -219,7 +219,7 @@ function info() {
function buildWrapper(targets, options) {
build.build(targets, options, function (err) {
if (err) {
- winston.error(err);
+ winston.error(err.stack);
process.exit(1);
}
process.exit(0);
diff --git a/src/cli/reset.js b/src/cli/reset.js
index ad3cd1b2c3..e913de916c 100644
--- a/src/cli/reset.js
+++ b/src/cli/reset.js
@@ -141,7 +141,7 @@ async function resetPlugin(pluginId) {
throw new Error('plugin-not-active');
}
} catch (err) {
- winston.error('[reset] Could not disable plugin: ' + pluginId + ' encountered error %s', err);
+ winston.error('[reset] Could not disable plugin: ' + pluginId + ' encountered error %s', err.stack);
throw err;
}
}
diff --git a/src/cli/setup.js b/src/cli/setup.js
index 897356b945..4c8ff06188 100644
--- a/src/cli/setup.js
+++ b/src/cli/setup.js
@@ -51,7 +51,7 @@ function setup(initConfig) {
console.log('\n' + separator + '\n');
if (err) {
- winston.error('There was a problem completing NodeBB setup', err);
+ winston.error('There was a problem completing NodeBB setup', err.stack);
throw err;
} else {
if (data.hasOwnProperty('password')) {
diff --git a/src/controllers/admin/dashboard.js b/src/controllers/admin/dashboard.js
index 73c50e468f..bf9081ced9 100644
--- a/src/controllers/admin/dashboard.js
+++ b/src/controllers/admin/dashboard.js
@@ -67,10 +67,9 @@ async function getNotices() {
async function getLatestVersion() {
try {
- const result = await versions.getLatestVersion();
- return result;
+ return await versions.getLatestVersion();
} catch (err) {
- winston.error('[acp] Failed to fetch latest version', err);
+ winston.error('[acp] Failed to fetch latest version', err.stack);
}
return null;
}
diff --git a/src/controllers/admin/info.js b/src/controllers/admin/info.js
index 4c1182e6f7..87f808a2e5 100644
--- a/src/controllers/admin/info.js
+++ b/src/controllers/admin/info.js
@@ -52,7 +52,7 @@ pubsub.on('sync:node:info:start', async function () {
data.id = os.hostname() + ':' + nconf.get('port');
pubsub.publish('sync:node:info:end', { data: data, id: data.id });
} catch (err) {
- winston.error(err);
+ winston.error(err.stack);
}
});
@@ -99,7 +99,7 @@ async function getGitInfo() {
function get(cmd, callback) {
exec(cmd, function (err, stdout) {
if (err) {
- winston.error(err);
+ winston.error(err.stack);
}
callback(null, stdout ? stdout.replace(/\n$/, '') : 'no-git-info');
});
diff --git a/src/controllers/admin/logs.js b/src/controllers/admin/logs.js
index bbdd20cca8..51ed116eca 100644
--- a/src/controllers/admin/logs.js
+++ b/src/controllers/admin/logs.js
@@ -12,7 +12,7 @@ logsController.get = async function (req, res) {
try {
logs = await meta.logs.get();
} catch (err) {
- winston.error(err);
+ winston.error(err.stack);
}
res.render('admin/advanced/logs', {
data: validator.escape(logs),
diff --git a/src/controllers/admin/plugins.js b/src/controllers/admin/plugins.js
index 4bfefff5b4..6467f27b49 100644
--- a/src/controllers/admin/plugins.js
+++ b/src/controllers/admin/plugins.js
@@ -52,7 +52,7 @@ async function getPlugins(matching) {
const pluginsData = await plugins.list(matching);
return pluginsData || [];
} catch (err) {
- winston.error(err);
+ winston.error(err.stack);
return [];
}
}
diff --git a/src/controllers/topics.js b/src/controllers/topics.js
index 33f048b853..758650d75c 100644
--- a/src/controllers/topics.js
+++ b/src/controllers/topics.js
@@ -143,7 +143,7 @@ function markAsRead(req, tid) {
if (req.loggedIn) {
topics.markAsRead([tid], req.uid, function (err, markedRead) {
if (err) {
- return winston.error(err);
+ return winston.error(err.stack);
}
if (markedRead) {
topics.pushUnreadCount(req.uid);
diff --git a/src/controllers/user.js b/src/controllers/user.js
index 3c55a5f642..6d197f3239 100644
--- a/src/controllers/user.js
+++ b/src/controllers/user.js
@@ -1,18 +1,9 @@
'use strict';
-const _ = require('lodash');
const path = require('path');
-const fs = require('fs');
-const winston = require('winston');
-const json2csvAsync = require('json2csv').parseAsync;
-const archiver = require('archiver');
-const db = require('../database');
const user = require('../user');
const meta = require('../meta');
-const posts = require('../posts');
-const batch = require('../batch');
-const events = require('../events');
const privileges = require('../privileges');
const accountHelpers = require('./accounts/helpers');
@@ -85,171 +76,34 @@ userController.getUserDataByUID = async function (callerUid, uid) {
return userData;
};
-userController.exportPosts = async function (req, res) {
- var payload = [];
- await batch.processSortedSet('uid:' + res.locals.uid + ':posts', async function (pids) {
- let postData = await posts.getPostsData(pids);
- // Remove empty post references and convert newlines in content
- postData = postData.filter(Boolean).map(function (post) {
- post.content = '"' + String(post.content || '').replace(/\n/g, '\\n').replace(/"/g, '\\"') + '"';
- return post;
- });
- payload = payload.concat(postData);
- }, {
- batch: 500,
- });
-
- const fields = payload.length ? Object.keys(payload[0]) : [];
- const opts = { fields };
- const csv = await json2csvAsync(payload, opts);
- res.set('Content-Type', 'text/csv').set('Content-Disposition', 'attachment; filename="' + res.locals.uid + '_posts.csv"').send(csv);
+userController.exportPosts = async function (req, res, next) {
+ sendExport(res.locals.uid + '_posts.csv', 'text/csv', res, next);
};
userController.exportUploads = function (req, res, next) {
- const targetUid = res.locals.uid;
- const archivePath = path.join(__dirname, '../../build/export', targetUid + '_uploads.zip');
- const archive = archiver('zip', {
- zlib: { level: 9 }, // Sets the compression level.
- });
- const maxAge = 1000 * 60 * 60 * 24; // 1 day
- const rootDirectory = path.join(__dirname, '../../public/uploads/');
- const trimPath = function (path) {
- return path.replace(rootDirectory, '');
- };
- let isFresh = false;
- const sendFile = function () {
- events.log({
- type: 'export:uploads',
- uid: req.uid,
- targetUid: targetUid,
- ip: req.ip,
- fresh: isFresh,
- });
+ sendExport(res.locals.uid + '_uploads.zip', 'application/zip', res, next);
+};
- res.sendFile(targetUid + '_uploads.zip', {
- root: path.join(__dirname, '../../build/export'),
- headers: {
- 'Content-Disposition': 'attachment; filename=' + targetUid + '_uploads.zip',
- maxAge: maxAge,
- },
- });
- };
+userController.exportProfile = async function (req, res, next) {
+ sendExport(res.locals.uid + '_profile.json', 'application/json', res, next);
+};
- // Check for existing file, if exists and is < 1 day in age, send this instead
- try {
- fs.accessSync(archivePath, fs.constants.F_OK | fs.constants.R_OK);
- isFresh = (Date.now() - fs.statSync(archivePath).mtimeMs) < maxAge;
- if (isFresh) {
- return sendFile();
- }
- } catch (err) {
- // File doesn't exist, continue
- }
-
- const output = fs.createWriteStream(archivePath);
- output.on('close', sendFile);
-
- archive.on('warning', function (err) {
- switch (err.code) {
- case 'ENOENT':
- winston.warn('[user/export/uploads] File not found: ' + trimPath(err.path));
- break;
-
- default:
- winston.warn('[user/export/uploads] Unexpected warning: ' + err.message);
- break;
- }
- });
-
- archive.on('error', function (err) {
- switch (err.code) {
- case 'EACCES':
- winston.error('[user/export/uploads] File inaccessible: ' + trimPath(err.path));
- break;
-
- default:
- winston.error('[user/export/uploads] Unable to construct archive: ' + err.message);
- break;
- }
-
- res.sendStatus(500);
- });
-
- archive.pipe(output);
- winston.verbose('[user/export/uploads] Collating uploads for uid ' + targetUid);
- user.collateUploads(targetUid, archive, function (err) {
+function sendExport(filename, type, res, next) {
+ res.sendFile(filename, {
+ root: path.join(__dirname, '../../build/export'),
+ headers: {
+ 'Content-Type': type,
+ 'Content-Disposition': 'attachment; filename=' + filename,
+ },
+ }, function (err) {
if (err) {
+ if (err.code === 'ENOENT') {
+ res.locals.isAPI = false;
+ return next();
+ }
return next(err);
}
-
- archive.finalize();
});
-};
-
-userController.exportProfile = async function (req, res) {
- const targetUid = parseInt(res.locals.uid, 10);
- const [userData, userSettings, ips, sessions, usernames, emails, bookmarks, watchedTopics, upvoted, downvoted, following] = await Promise.all([
- db.getObject('user:' + targetUid),
- db.getObject('user:' + targetUid + ':settings'),
- user.getIPs(targetUid, 9),
- user.auth.getSessions(targetUid, req.sessionID),
- user.getHistory('user:' + targetUid + ':usernames'),
- user.getHistory('user:' + targetUid + ':emails'),
- getSetData('uid:' + targetUid + ':bookmarks', 'post:', targetUid),
- getSetData('uid:' + targetUid + ':followed_tids', 'topic:', targetUid),
- getSetData('uid:' + targetUid + ':upvote', 'post:', targetUid),
- getSetData('uid:' + targetUid + ':downvote', 'post:', targetUid),
- getSetData('following:' + targetUid, 'user:', targetUid),
- ]);
- delete userData.password;
- const followingData = following.map(u => ({ username: u.username, uid: u.uid }));
-
- let chatData = [];
- await batch.processSortedSet('uid:' + targetUid + ':chat:rooms', async (roomIds) => {
- var result = await Promise.all(roomIds.map(roomId => getRoomMessages(targetUid, roomId)));
- chatData = chatData.concat(_.flatten(result));
- }, { batch: 100 });
-
- res.set('Content-Type', 'application/json')
- .set('Content-Disposition', 'attachment; filename="' + targetUid + '_profile.json"')
- .send({
- user: userData,
- settings: userSettings,
- ips: ips,
- sessions: sessions,
- usernames: usernames,
- emails: emails,
- messages: chatData,
- bookmarks: bookmarks,
- watchedTopics: watchedTopics,
- upvoted: upvoted,
- downvoted: downvoted,
- following: followingData,
- });
-};
-
-async function getRoomMessages(uid, roomId) {
- let data = [];
- await batch.processSortedSet('uid:' + uid + ':chat:room:' + roomId + ':mids', async (mids) => {
- const messageData = await db.getObjects(mids.map(mid => 'message:' + mid));
- data = data.concat(messageData.filter(m => m && m.fromuid === uid && !m.system)
- .map(m => ({ content: m.content, timestamp: m.timestamp }))
- );
- }, { batch: 500 });
- return data;
-}
-
-async function getSetData(set, keyPrefix, uid) {
- let data = [];
- await batch.processSortedSet(set, async (ids) => {
- if (keyPrefix === 'post:') {
- ids = await privileges.posts.filter('topics:read', ids, uid);
- } else if (keyPrefix === 'topic:') {
- ids = await privileges.topics.filterTids('topics:read', ids, uid);
- }
- data = data.concat(await db.getObjects(ids.map(id => keyPrefix + id)));
- }, { batch: 500 });
- return data;
}
require('../promisify')(userController, [
diff --git a/src/database/postgres/pubsub.js b/src/database/postgres/pubsub.js
index 3b9d03f007..4a3f280936 100644
--- a/src/database/postgres/pubsub.js
+++ b/src/database/postgres/pubsub.js
@@ -13,13 +13,13 @@ const PubSub = function () {
subClient.connect(function (err) {
if (err) {
- winston.error(err);
+ winston.error(err.stack);
return;
}
subClient.query('LISTEN pubsub', function (err) {
if (err) {
- winston.error(err);
+ winston.error(err.stack);
}
});
diff --git a/src/database/redis.js b/src/database/redis.js
index c235712ef0..82a6eead47 100644
--- a/src/database/redis.js
+++ b/src/database/redis.js
@@ -40,7 +40,7 @@ redisModule.init = function (callback) {
callback = callback || function () { };
redisModule.client = connection.connect(nconf.get('redis'), function (err) {
if (err) {
- winston.error('NodeBB could not connect to your Redis database. Redis returned the following error', err);
+ winston.error('NodeBB could not connect to your Redis database. Redis returned the following error', err.stack);
return callback(err);
}
require('./redis/promisify')(redisModule.client);
diff --git a/src/database/redis/connection.js b/src/database/redis/connection.js
index 50ee98baa5..b291b1f284 100644
--- a/src/database/redis/connection.js
+++ b/src/database/redis/connection.js
@@ -58,7 +58,7 @@ connection.connect = function (options, callback) {
if (dbIdx >= 0) {
cxn.select(dbIdx, function (err) {
if (err) {
- winston.error('NodeBB could not select Redis database. Redis returned the following error', err);
+ winston.error('NodeBB could not select Redis database. Redis returned the following error', err.stack);
throw err;
}
});
diff --git a/src/database/redis/hash.js b/src/database/redis/hash.js
index afa2b7e016..d5636cdfe7 100644
--- a/src/database/redis/hash.js
+++ b/src/database/redis/hash.js
@@ -154,7 +154,11 @@ module.exports = function (module) {
};
module.deleteObjectFields = async function (key, fields) {
- if (!Array.isArray(fields) || !fields.length) {
+ if (!key || !Array.isArray(fields) || !fields.length) {
+ return;
+ }
+ fields = fields.filter(Boolean);
+ if (!fields.length) {
return;
}
await module.client.async.hdel(key, fields);
diff --git a/src/emailer.js b/src/emailer.js
index 2f7bb1e147..51211aa1ec 100644
--- a/src/emailer.js
+++ b/src/emailer.js
@@ -193,7 +193,7 @@ Emailer.send = async function (template, uid, params) {
try {
await Emailer.sendToEmail(template, userData.email, userSettings.userLang, params);
} catch (err) {
- winston.error(err);
+ winston.error(err.stack);
}
};
@@ -286,7 +286,7 @@ Emailer.sendViaFallback = function (data, callback) {
winston.verbose('[emailer] Sending email to uid ' + data.uid + ' (' + data.to + ')');
Emailer.fallbackTransport.sendMail(data, function (err) {
if (err) {
- winston.error(err);
+ winston.error(err.stack);
}
callback();
});
@@ -322,7 +322,7 @@ async function buildCustomTemplates(config) {
Benchpress.flush();
winston.verbose('[emailer] Built custom email templates');
} catch (err) {
- winston.error('[emailer] Failed to build custom email templates', err);
+ winston.error('[emailer] Failed to build custom email templates', err.stack);
}
}
diff --git a/src/file.js b/src/file.js
index 565f7b7f27..cb384ec64a 100644
--- a/src/file.js
+++ b/src/file.js
@@ -30,6 +30,9 @@ file.saveFileToLocal = async function (filename, folder, tempPath) {
filename = filename.split('.').map(name => utils.slugify(name)).join('.');
const uploadPath = path.join(nconf.get('upload_path'), folder, filename);
+ if (!uploadPath.startsWith(nconf.get('upload_path'))) {
+ throw new Error('[[error:invalid-path]]');
+ }
winston.verbose('Saving file ' + filename + ' to : ' + uploadPath);
await mkdirp(path.dirname(uploadPath));
diff --git a/src/flags.js b/src/flags.js
index 890617fa99..6668895098 100644
--- a/src/flags.js
+++ b/src/flags.js
@@ -78,7 +78,7 @@ Flags.init = async function () {
const data = await plugins.fireHook('filter:flags.getFilters', hookData);
Flags._filters = data.filters;
} catch (err) {
- winston.error('[flags/init] Could not retrieve filters', err);
+ winston.error('[flags/init] Could not retrieve filters', err.stack);
Flags._filters = {};
}
};
diff --git a/src/groups/data.js b/src/groups/data.js
index 19a1119b8e..c866902b4c 100644
--- a/src/groups/data.js
+++ b/src/groups/data.js
@@ -25,13 +25,8 @@ module.exports = function (Groups) {
return memo;
}, []);
- let groupData;
const keys = groupNames.map(groupName => 'group:' + groupName);
- if (fields.length) {
- groupData = await db.getObjectsFields(keys, fields);
- } else {
- groupData = await db.getObjects(keys);
- }
+ const groupData = await (fields.length ? db.getObjectsFields(keys, fields) : db.getObjects(keys));
if (ephemeralIdx.length) {
ephemeralIdx.forEach(function (idx) {
groupData[idx] = Groups.getEphemeralGroup(groupNames[idx]);
diff --git a/src/groups/join.js b/src/groups/join.js
index 1a64c3ca08..06519ce57b 100644
--- a/src/groups/join.js
+++ b/src/groups/join.js
@@ -82,7 +82,7 @@ module.exports = function (Groups) {
});
} catch (err) {
if (err && err.message !== '[[error:group-already-exists]]') {
- winston.error('[groups.join] Could not create new hidden group', err);
+ winston.error('[groups.join] Could not create new hidden group', err.stack);
throw err;
}
}
diff --git a/src/image.js b/src/image.js
index 4bf588621c..e7e4652fed 100644
--- a/src/image.js
+++ b/src/image.js
@@ -101,7 +101,7 @@ image.stripEXIF = async function (path) {
const sharp = requireSharp();
await sharp(buffer, { failOnError: true }).rotate().toFile(path);
} catch (err) {
- winston.error(err);
+ winston.error(err.stack);
}
};
diff --git a/src/install.js b/src/install.js
index 634e932fd3..78410e98fc 100644
--- a/src/install.js
+++ b/src/install.js
@@ -607,7 +607,7 @@ install.save = function (server_conf, callback) {
fs.writeFile(serverConfigPath, JSON.stringify(server_conf, null, 4), function (err) {
if (err) {
- winston.error('Error saving server configuration!', err);
+ winston.error('Error saving server configuration!', err.stack);
return callback(err);
}
diff --git a/src/logger.js b/src/logger.js
index 632c9b84ca..9db812143d 100644
--- a/src/logger.js
+++ b/src/logger.js
@@ -88,7 +88,7 @@ Logger.open = function (value) {
if (stream) {
stream.on('error', function (err) {
- winston.error(err);
+ winston.error(err.stack);
});
}
} else {
diff --git a/src/messaging/data.js b/src/messaging/data.js
index 9fbf14eb63..b20e514de4 100644
--- a/src/messaging/data.js
+++ b/src/messaging/data.js
@@ -18,13 +18,7 @@ module.exports = function (Messaging) {
}
const keys = mids.map(mid => 'message:' + mid);
- let messages;
- if (fields.length) {
- messages = await db.getObjectsFields(keys, fields);
- } else {
- messages = await db.getObjects(keys);
- }
-
+ const messages = await (fields.length ? db.getObjectsFields(keys, fields) : db.getObjects(keys));
messages.forEach(message => modifyMessage(message, fields));
return messages;
};
diff --git a/src/meta/build.js b/src/meta/build.js
index a6315edeeb..392f541f8d 100644
--- a/src/meta/build.js
+++ b/src/meta/build.js
@@ -114,7 +114,7 @@ function beforeBuild(targets, callback) {
},
], function (err) {
if (err) {
- winston.error('[build] Encountered error preparing for build', err);
+ winston.error('[build] Encountered error preparing for build', err.stack);
return callback(err);
}
@@ -218,7 +218,7 @@ exports.build = function (targets, options, callback) {
},
], function (err) {
if (err) {
- winston.error('[build] Encountered error during build step', err);
+ winston.error('[build] Encountered error during build step', err.stack);
return callback(err);
}
diff --git a/src/meta/configs.js b/src/meta/configs.js
index da07f68fbd..c8794916d1 100644
--- a/src/meta/configs.js
+++ b/src/meta/configs.js
@@ -44,7 +44,7 @@ function deserialize(config) {
try {
deserialized[key] = JSON.parse(config[key] || '[]');
} catch (err) {
- winston.error(err);
+ winston.error(err.stack);
deserialized[key] = defaults[key];
}
} else {
diff --git a/src/meta/errors.js b/src/meta/errors.js
index 43b92ba4b1..6aff66da17 100644
--- a/src/meta/errors.js
+++ b/src/meta/errors.js
@@ -30,7 +30,7 @@ Errors.writeData = async function () {
await db.sortedSetIncrBy('errors:404', _counters[key], key);
}
} catch (err) {
- winston.error(err);
+ winston.error(err.stack);
}
};
diff --git a/src/middleware/render.js b/src/middleware/render.js
index 1e9d20b0b0..a82bac03b5 100644
--- a/src/middleware/render.js
+++ b/src/middleware/render.js
@@ -113,7 +113,7 @@ module.exports = function (middleware) {
try {
p = utils.slugify(decodeURIComponent(p));
} catch (err) {
- winston.error(err);
+ winston.error(err.stack);
p = '';
}
p = validator.escape(String(p));
diff --git a/src/notifications.js b/src/notifications.js
index 12482b0272..1b307cf9b6 100644
--- a/src/notifications.js
+++ b/src/notifications.js
@@ -326,7 +326,7 @@ Notifications.prune = async function () {
}, { batch: 500, interval: 100 });
} catch (err) {
if (err) {
- winston.error('Encountered error pruning notifications', err);
+ winston.error('Encountered error pruning notifications', err.stack);
}
}
};
diff --git a/src/plugins/data.js b/src/plugins/data.js
index d127bd9bd5..76c780e8a6 100644
--- a/src/plugins/data.js
+++ b/src/plugins/data.js
@@ -48,7 +48,7 @@ Data.loadPluginInfo = async function (pluginPath) {
} catch (err) {
var pluginDir = path.basename(pluginPath);
- winston.error('[plugins/' + pluginDir + '] Error in plugin.json or package.json!', err);
+ winston.error('[plugins/' + pluginDir + '] Error in plugin.json or package.json!', err.stack);
throw new Error('[[error:parse-error]]');
}
return pluginData;
diff --git a/src/plugins/index.js b/src/plugins/index.js
index 1a04d7064a..9d5e93abce 100644
--- a/src/plugins/index.js
+++ b/src/plugins/index.js
@@ -291,7 +291,7 @@ Plugins.showInstalled = async function () {
pluginData.error = false;
return pluginData;
} catch (err) {
- winston.error(err);
+ winston.error(err.stack);
}
}
const plugins = await Promise.all(pluginPaths.map(file => load(file)));
diff --git a/src/plugins/usage.js b/src/plugins/usage.js
index 1c1d86478f..78d95c3e35 100644
--- a/src/plugins/usage.js
+++ b/src/plugins/usage.js
@@ -33,7 +33,7 @@ module.exports = function (Plugins) {
timeout: 5000,
}, function (err, res, body) {
if (err) {
- return winston.error(err);
+ return winston.error(err.stack);
}
if (res.statusCode !== 200) {
winston.error('[plugins.submitUsageData] received ' + res.statusCode + ' ' + body);
diff --git a/src/posts/data.js b/src/posts/data.js
index 8d5ea80bed..bc4ba790d1 100644
--- a/src/posts/data.js
+++ b/src/posts/data.js
@@ -15,12 +15,7 @@ module.exports = function (Posts) {
return [];
}
const keys = pids.map(pid => 'post:' + pid);
- let postData;
- if (fields.length) {
- postData = await db.getObjectsFields(keys, fields);
- } else {
- postData = await db.getObjects(keys);
- }
+ const postData = await (fields.length ? db.getObjectsFields(keys, fields) : db.getObjects(keys));
const result = await plugins.fireHook('filter:post.getFields', {
pids: pids,
posts: postData,
diff --git a/src/prestart.js b/src/prestart.js
index 49f6336499..d49126bd18 100644
--- a/src/prestart.js
+++ b/src/prestart.js
@@ -33,7 +33,7 @@ function setupWinston() {
}
winston.configure({
- level: nconf.get('log-level') || (global.env === 'production' ? 'info' : 'verbose'),
+ level: nconf.get('log-level') || (process.env.NODE_ENV === 'production' ? 'info' : 'verbose'),
format: winston.format.combine.apply(null, formats),
transports: [
new winston.transports.Console({
@@ -71,10 +71,6 @@ function loadConfig(configFile) {
nconf.set('upload_path', path.resolve(nconf.get('base_dir'), nconf.get('upload_path')));
nconf.set('upload_url', '/assets/uploads');
- if (nconf.get('url')) {
- nconf.set('url_parsed', url.parse(nconf.get('url')));
- }
-
// Explicitly cast 'jobsDisabled' as Bool
var castAsBool = ['jobsDisabled'];
nconf.stores.env.readOnly = false;
@@ -87,6 +83,23 @@ function loadConfig(configFile) {
nconf.stores.env.readOnly = true;
nconf.set('runJobs', nconf.get('isPrimary') === 'true' && !nconf.get('jobsDisabled'));
+
+ // nconf defaults, if not set in config
+ if (!nconf.get('sessionKey')) {
+ nconf.set('sessionKey', 'express.sid');
+ }
+
+ if (nconf.get('url')) {
+ nconf.set('url_parsed', url.parse(nconf.get('url')));
+ // Parse out the relative_url and other goodies from the configured URL
+ const urlObject = url.parse(nconf.get('url'));
+ const relativePath = urlObject.pathname !== '/' ? urlObject.pathname.replace(/\/+$/, '') : '';
+ nconf.set('base_url', urlObject.protocol + '//' + urlObject.host);
+ nconf.set('secure', urlObject.protocol === 'https:');
+ nconf.set('use_port', !!urlObject.port);
+ nconf.set('relative_path', relativePath);
+ nconf.set('port', nconf.get('PORT') || nconf.get('port') || urlObject.port || (nconf.get('PORT_ENV_VAR') ? nconf.get(nconf.get('PORT_ENV_VAR')) : false) || 4567);
+ }
}
function versionCheck() {
diff --git a/src/socket.io/admin/user.js b/src/socket.io/admin/user.js
index e9a7994ee3..fde65426cd 100644
--- a/src/socket.io/admin/user.js
+++ b/src/socket.io/admin/user.js
@@ -173,7 +173,7 @@ async function deleteUsers(socket, uids, method) {
try {
await Promise.all(uids.map(uid => doDelete(uid)));
} catch (err) {
- winston.error(err);
+ winston.error(err.stack);
}
}
diff --git a/src/socket.io/user/profile.js b/src/socket.io/user/profile.js
index 403621bc86..0886b1e24c 100644
--- a/src/socket.io/user/profile.js
+++ b/src/socket.io/user/profile.js
@@ -1,9 +1,13 @@
'use strict';
+const winston = require('winston');
+
const user = require('../../user');
const meta = require('../../meta');
const events = require('../../events');
const privileges = require('../../privileges');
+const notifications = require('../../notifications');
+const db = require('../../database');
module.exports = function (SocketUser) {
SocketUser.changeUsernameEmail = async function (socket, data) {
@@ -140,4 +144,59 @@ module.exports = function (SocketUser) {
await user.blocks[isBlocked ? 'remove' : 'add'](data.blockeeUid, data.blockerUid);
return !isBlocked;
};
+
+ SocketUser.exportProfile = async function (socket, data) {
+ await doExport(socket, data, 'profile');
+ };
+
+ SocketUser.exportPosts = async function (socket, data) {
+ await doExport(socket, data, 'posts');
+ };
+
+ SocketUser.exportUploads = async function (socket, data) {
+ await doExport(socket, data, 'uploads');
+ };
+
+ async function doExport(socket, data, type) {
+ if (!socket.uid) {
+ throw new Error('[[error:invalid-uid]]');
+ }
+
+ if (!data || !data.uid) {
+ throw new Error('[[error:invalid-data]]');
+ }
+
+ await user.isAdminOrSelf(socket.uid, data.uid);
+
+ const count = await db.incrObjectField('locks', 'export:' + data.uid + type);
+ if (count > 1) {
+ throw new Error('[[error:already-exporting]]');
+ }
+
+ const child = require('child_process').fork('./src/user/jobs/export-' + type + '.js', [], {
+ env: process.env,
+ });
+ child.send({ uid: data.uid });
+ child.on('error', async function (err) {
+ winston.error(err.stack);
+ await db.deleteObjectField('locks', 'export:' + data.uid + type);
+ });
+ child.on('exit', async function () {
+ await db.deleteObjectField('locks', 'export:' + data.uid + type);
+ const userData = await user.getUserFields(data.uid, ['username', 'userslug']);
+ const n = await notifications.create({
+ bodyShort: '[[notifications:' + type + '-exported, ' + userData.username + ']]',
+ path: '/api/user/uid/' + userData.userslug + '/export/' + type,
+ nid: type + ':export:' + data.uid,
+ from: data.uid,
+ });
+ await notifications.push(n, [socket.uid]);
+ await events.log({
+ type: 'export:' + type,
+ uid: socket.uid,
+ targetUid: data.uid,
+ ip: socket.ip,
+ });
+ });
+ }
};
diff --git a/src/start.js b/src/start.js
index 0be889173f..062a601cc6 100644
--- a/src/start.js
+++ b/src/start.js
@@ -1,7 +1,6 @@
'use strict';
const nconf = require('nconf');
-const url = require('url');
const winston = require('winston');
const start = module.exports;
@@ -9,8 +8,6 @@ const start = module.exports;
start.start = async function () {
const db = require('./database');
- setupConfigs();
-
printStartupInfo();
addProcessHandlers();
@@ -81,21 +78,6 @@ async function runUpgrades() {
}
}
-function setupConfigs() {
- // nconf defaults, if not set in config
- if (!nconf.get('sessionKey')) {
- nconf.set('sessionKey', 'express.sid');
- }
- // Parse out the relative_url and other goodies from the configured URL
- const urlObject = url.parse(nconf.get('url'));
- const relativePath = urlObject.pathname !== '/' ? urlObject.pathname.replace(/\/+$/, '') : '';
- nconf.set('base_url', urlObject.protocol + '//' + urlObject.host);
- nconf.set('secure', urlObject.protocol === 'https:');
- nconf.set('use_port', !!urlObject.port);
- nconf.set('relative_path', relativePath);
- nconf.set('port', nconf.get('PORT') || nconf.get('port') || urlObject.port || (nconf.get('PORT_ENV_VAR') ? nconf.get(nconf.get('PORT_ENV_VAR')) : false) || 4567);
-}
-
function printStartupInfo() {
if (nconf.get('isPrimary') === 'true') {
winston.info('Initializing NodeBB v%s %s', nconf.get('version'), nconf.get('url'));
@@ -113,7 +95,7 @@ function addProcessHandlers() {
process.on('SIGINT', shutdown);
process.on('SIGHUP', restart);
process.on('uncaughtException', function (err) {
- winston.error(err);
+ winston.error(err.stack);
require('./meta').js.killMinifier();
shutdown(1);
diff --git a/src/user/create.js b/src/user/create.js
index a25595ba5f..a205851323 100644
--- a/src/user/create.js
+++ b/src/user/create.js
@@ -14,10 +14,30 @@ module.exports = function (User) {
if (data.email !== undefined) {
data.email = String(data.email).trim();
}
- const timestamp = data.timestamp || Date.now();
await User.isDataValid(data);
+ try {
+ await lock(data.username, '[[error:username-taken]]');
+ if (data.email) {
+ await lock(data.email, '[[error:email-taken]]');
+ }
+ return await create(data);
+ } finally {
+ await db.deleteObjectFields('locks', [data.username, data.email]);
+ }
+ };
+
+ async function lock(value, error) {
+ const count = await db.incrObjectField('locks', value);
+ if (count > 1) {
+ throw new Error(error);
+ }
+ }
+
+ async function create(data) {
+ const timestamp = data.timestamp || Date.now();
+
let userData = {
username: data.username,
userslug: data.userslug,
@@ -70,7 +90,7 @@ module.exports = function (User) {
if (userData.email) {
bulkAdd.push(['email:uid', userData.uid, userData.email.toLowerCase()]);
bulkAdd.push(['email:sorted', 0, userData.email.toLowerCase() + ':' + userData.uid]);
- bulkAdd.push(['user:' + userData.uid + ':emails', timestamp, userData.email]);
+ bulkAdd.push(['user:' + userData.uid + ':emails', timestamp, userData.email + ':' + timestamp]);
}
await Promise.all([
@@ -92,7 +112,7 @@ module.exports = function (User) {
}
plugins.fireHook('action:user.create', { user: userData, data: data });
return userData.uid;
- };
+ }
async function storePassword(uid, password) {
if (!password) {
diff --git a/src/user/data.js b/src/user/data.js
index 07670a7bfd..400d8ef472 100644
--- a/src/user/data.js
+++ b/src/user/data.js
@@ -66,8 +66,12 @@ module.exports = function (User) {
}
let users = await db.getObjectsFields(uniqueUids.map(uid => 'user:' + uid), fields);
- users = uidsToUsers(uids, uniqueUids, users);
-
+ const result = await plugins.fireHook('filter:user.getFields', {
+ uids: uniqueUids,
+ users: users,
+ fields: fields,
+ });
+ users = uidsToUsers(uids, uniqueUids, result.users);
return await modifyUserData(users, fields, fieldsToRemove);
};
diff --git a/src/user/digest.js b/src/user/digest.js
index cebabccf29..90b85bc038 100644
--- a/src/user/digest.js
+++ b/src/user/digest.js
@@ -35,7 +35,7 @@ Digest.execute = async function (payload) {
});
winston.info('[user/jobs] Digest (' + payload.interval + ') scheduling completed. Sending emails; this may take some time...');
} catch (err) {
- winston.error('[user/jobs] Could not send digests (' + payload.interval + ')', err);
+ winston.error('[user/jobs] Could not send digests (' + payload.interval + ')', err.stack);
throw err;
}
};
@@ -139,7 +139,7 @@ Digest.send = async function (data) {
showUnsubscribe: true,
});
} catch (err) {
- winston.error('[user/jobs] Could not send digest email', err);
+ winston.error('[user/jobs] Could not send digest email', err.stack);
}
if (data.interval !== 'alltime') {
diff --git a/src/user/follow.js b/src/user/follow.js
index 9e37a62a8d..c8c281f927 100644
--- a/src/user/follow.js
+++ b/src/user/follow.js
@@ -36,8 +36,6 @@ module.exports = function (User) {
['following:' + uid, now, theiruid],
['followers:' + theiruid, now, uid],
]),
- User.incrementUserFieldBy(uid, 'followingCount', 1),
- User.incrementUserFieldBy(theiruid, 'followerCount', 1),
]);
} else {
if (!isFollowing) {
@@ -48,10 +46,17 @@ module.exports = function (User) {
['following:' + uid, theiruid],
['followers:' + theiruid, uid],
]),
- User.decrementUserFieldBy(uid, 'followingCount', 1),
- User.decrementUserFieldBy(theiruid, 'followerCount', 1),
]);
}
+
+ const [followingCount, followerCount] = await Promise.all([
+ db.sortedSetCard('following:' + uid),
+ db.sortedSetCard('followers:' + theiruid),
+ ]);
+ await Promise.all([
+ User.setUserField(uid, 'followingCount', followingCount),
+ User.setUserField(theiruid, 'followerCount', followerCount),
+ ]);
}
User.getFollowing = async function (uid, start, stop) {
diff --git a/src/user/jobs/export-posts.js b/src/user/jobs/export-posts.js
new file mode 100644
index 0000000000..643fa25d71
--- /dev/null
+++ b/src/user/jobs/export-posts.js
@@ -0,0 +1,54 @@
+'use strict';
+
+const nconf = require('nconf');
+nconf.argv().env({
+ separator: '__',
+});
+
+const fs = require('fs');
+const path = require('path');
+const json2csvAsync = require('json2csv').parseAsync;
+
+process.env.NODE_ENV = process.env.NODE_ENV || 'production';
+
+// Alternate configuration file support
+const configFile = path.resolve(__dirname, '../../../', nconf.any(['config', 'CONFIG']) || 'config.json');
+const prestart = require('../../prestart');
+prestart.loadConfig(configFile);
+prestart.setupWinston();
+
+const db = require('../../database');
+const batch = require('../../batch');
+
+process.on('message', async function (msg) {
+ if (msg && msg.uid) {
+ await db.init();
+
+ const targetUid = msg.uid;
+ const filePath = path.join(__dirname, '../../../build/export', targetUid + '_posts.csv');
+
+ const posts = require('../../posts');
+
+ let payload = [];
+ await batch.processSortedSet('uid:' + targetUid + ':posts', async function (pids) {
+ let postData = await posts.getPostsData(pids);
+ // Remove empty post references and convert newlines in content
+ postData = postData.filter(Boolean).map(function (post) {
+ post.content = '"' + String(post.content || '').replace(/\n/g, '\\n').replace(/"/g, '\\"') + '"';
+ return post;
+ });
+ payload = payload.concat(postData);
+ }, {
+ batch: 500,
+ interval: 1000,
+ });
+
+ const fields = payload.length ? Object.keys(payload[0]) : [];
+ const opts = { fields };
+ const csv = await json2csvAsync(payload, opts);
+ await fs.promises.writeFile(filePath, csv);
+
+ await db.close();
+ process.exit(0);
+ }
+});
diff --git a/src/user/jobs/export-profile.js b/src/user/jobs/export-profile.js
new file mode 100644
index 0000000000..7f506e09eb
--- /dev/null
+++ b/src/user/jobs/export-profile.js
@@ -0,0 +1,108 @@
+'use strict';
+
+const nconf = require('nconf');
+nconf.argv().env({
+ separator: '__',
+});
+
+const fs = require('fs');
+const path = require('path');
+const _ = require('lodash');
+
+process.env.NODE_ENV = process.env.NODE_ENV || 'production';
+
+// Alternate configuration file support
+const configFile = path.resolve(__dirname, '../../../', nconf.any(['config', 'CONFIG']) || 'config.json');
+const prestart = require('../../prestart');
+prestart.loadConfig(configFile);
+prestart.setupWinston();
+
+const db = require('../../database');
+const batch = require('../../batch');
+
+process.on('message', async function (msg) {
+ if (msg && msg.uid) {
+ await db.init();
+ await db.initSessionStore();
+
+ const targetUid = msg.uid;
+
+ const profileFile = targetUid + '_profile.json';
+ const profilePath = path.join(__dirname, '../../../build/export', profileFile);
+
+ const user = require('../index');
+ const [userData, userSettings, ips, sessions, usernames, emails, bookmarks, watchedTopics, upvoted, downvoted, following] = await Promise.all([
+ db.getObject('user:' + targetUid),
+ db.getObject('user:' + targetUid + ':settings'),
+ user.getIPs(targetUid, 9),
+ user.auth.getSessions(targetUid),
+ user.getHistory('user:' + targetUid + ':usernames'),
+ user.getHistory('user:' + targetUid + ':emails'),
+ getSetData('uid:' + targetUid + ':bookmarks', 'post:', targetUid),
+ getSetData('uid:' + targetUid + ':followed_tids', 'topic:', targetUid),
+ getSetData('uid:' + targetUid + ':upvote', 'post:', targetUid),
+ getSetData('uid:' + targetUid + ':downvote', 'post:', targetUid),
+ getSetData('following:' + targetUid, 'user:', targetUid),
+ ]);
+ delete userData.password;
+
+ let chatData = [];
+ await batch.processSortedSet('uid:' + targetUid + ':chat:rooms', async (roomIds) => {
+ var result = await Promise.all(roomIds.map(roomId => getRoomMessages(targetUid, roomId)));
+ chatData = chatData.concat(_.flatten(result));
+ }, { batch: 100, interval: 1000 });
+
+ await fs.promises.writeFile(profilePath, JSON.stringify({
+ user: userData,
+ settings: userSettings,
+ ips: ips,
+ sessions: sessions,
+ usernames: usernames,
+ emails: emails,
+ messages: chatData,
+ bookmarks: bookmarks,
+ watchedTopics: watchedTopics,
+ upvoted: upvoted,
+ downvoted: downvoted,
+ following: following,
+ }, null, 4));
+
+ await db.close();
+ process.exit(0);
+ }
+});
+
+async function getRoomMessages(uid, roomId) {
+ const batch = require('../../batch');
+ let data = [];
+ await batch.processSortedSet('uid:' + uid + ':chat:room:' + roomId + ':mids', async (mids) => {
+ const messageData = await db.getObjects(mids.map(mid => 'message:' + mid));
+ data = data.concat(messageData.filter(m => m && m.fromuid === uid && !m.system)
+ .map(m => ({ content: m.content, timestamp: m.timestamp }))
+ );
+ }, { batch: 500, interval: 1000 });
+ return data;
+}
+
+async function getSetData(set, keyPrefix, uid) {
+ const privileges = require('../../privileges');
+ const batch = require('../../batch');
+ let data = [];
+ await batch.processSortedSet(set, async (ids) => {
+ if (keyPrefix === 'post:') {
+ ids = await privileges.posts.filter('topics:read', ids, uid);
+ } else if (keyPrefix === 'topic:') {
+ ids = await privileges.topics.filterTids('topics:read', ids, uid);
+ }
+ let objData = await db.getObjects(ids.map(id => keyPrefix + id));
+ if (keyPrefix === 'post:') {
+ objData = objData.map(o => _.pick(o, ['pid', 'content', 'timestamp']));
+ } else if (keyPrefix === 'topic:') {
+ objData = objData.map(o => _.pick(o, ['tid', 'title', 'timestamp']));
+ } else if (keyPrefix === 'user:') {
+ objData = objData.map(o => _.pick(o, ['uid', 'username']));
+ }
+ data = data.concat(objData);
+ }, { batch: 500, interval: 1000 });
+ return data;
+}
diff --git a/src/user/jobs/export-uploads.js b/src/user/jobs/export-uploads.js
new file mode 100644
index 0000000000..af2bc64e97
--- /dev/null
+++ b/src/user/jobs/export-uploads.js
@@ -0,0 +1,76 @@
+'use strict';
+
+const nconf = require('nconf');
+nconf.argv().env({
+ separator: '__',
+});
+
+const fs = require('fs');
+const path = require('path');
+const archiver = require('archiver');
+const winston = require('winston');
+
+process.env.NODE_ENV = process.env.NODE_ENV || 'production';
+
+// Alternate configuration file support
+const configFile = path.resolve(__dirname, '../../../', nconf.any(['config', 'CONFIG']) || 'config.json');
+const prestart = require('../../prestart');
+prestart.loadConfig(configFile);
+prestart.setupWinston();
+
+const db = require('../../database');
+
+process.on('message', async function (msg) {
+ if (msg && msg.uid) {
+ await db.init();
+
+ const targetUid = msg.uid;
+
+ const archivePath = path.join(__dirname, '../../../build/export', targetUid + '_uploads.zip');
+ const rootDirectory = path.join(__dirname, '../../../public/uploads/');
+
+ const user = require('../index');
+
+ const archive = archiver('zip', {
+ zlib: { level: 9 }, // Sets the compression level.
+ });
+
+ archive.on('warning', function (err) {
+ switch (err.code) {
+ case 'ENOENT':
+ winston.warn('[user/export/uploads] File not found: ' + err.path);
+ break;
+
+ default:
+ winston.warn('[user/export/uploads] Unexpected warning: ' + err.message);
+ break;
+ }
+ });
+
+ archive.on('error', function (err) {
+ const trimPath = function (path) {
+ return path.replace(rootDirectory, '');
+ };
+ switch (err.code) {
+ case 'EACCES':
+ winston.error('[user/export/uploads] File inaccessible: ' + trimPath(err.path));
+ break;
+
+ default:
+ winston.error('[user/export/uploads] Unable to construct archive: ' + err.message);
+ break;
+ }
+ });
+
+ const output = fs.createWriteStream(archivePath);
+ output.on('close', async function () {
+ await db.close();
+ process.exit(0);
+ });
+
+ archive.pipe(output);
+ winston.verbose('[user/export/uploads] Collating uploads for uid ' + targetUid);
+ await user.collateUploads(targetUid, archive);
+ archive.finalize();
+ }
+});
diff --git a/src/user/notifications.js b/src/user/notifications.js
index fa30b0e2e1..fe22127c5a 100644
--- a/src/user/notifications.js
+++ b/src/user/notifications.js
@@ -190,7 +190,7 @@ UserNotifications.sendTopicNotificationToFollowers = async function (uid, topicD
await notifications.push(notifObj, followers);
} catch (err) {
- winston.error(err);
+ winston.error(err.stack);
}
};
diff --git a/src/user/picture.js b/src/user/picture.js
index 2d6811b99e..5419b062e5 100644
--- a/src/user/picture.js
+++ b/src/user/picture.js
@@ -45,9 +45,9 @@ module.exports = function (User) {
validateUpload(data, meta.config.maximumCoverImageSize, ['image/png', 'image/jpeg', 'image/bmp']);
- picture.path = await getTempPath(data);
+ picture.path = await image.writeImageDataToTempFile(data.imageData);
- const extension = file.typeToExtension(getMimeType(data));
+ const extension = file.typeToExtension(image.mimeFromBase64(data.imageData));
const filename = data.uid + '-profilecover' + extension;
const uploadData = await image.uploadImage(filename, 'profile', picture);
@@ -61,7 +61,7 @@ module.exports = function (User) {
url: uploadData.url,
};
} finally {
- file.delete(picture.path || (data.file && data.file.path));
+ file.delete(picture.path);
}
};
@@ -78,12 +78,12 @@ module.exports = function (User) {
validateUpload(data, meta.config.maximumProfileImageSize, User.getAllowedImageTypes());
- const extension = file.typeToExtension(getMimeType(data));
+ const extension = file.typeToExtension(image.mimeFromBase64(data.imageData));
if (!extension) {
throw new Error('[[error:invalid-image-extension]]');
}
- picture.path = await getTempPath(data);
+ picture.path = await image.writeImageDataToTempFile(data.imageData);
picture.path = await convertToPNG(picture.path);
await image.resizeImage({
@@ -101,36 +101,25 @@ module.exports = function (User) {
});
return uploadedImage;
} finally {
- file.delete(picture.path || (data.file && data.file.path));
+ file.delete(picture.path);
}
};
function validateUpload(data, maxSize, allowedTypes) {
- if (!data.imageData && !data.file) {
+ if (!data.imageData) {
throw new Error('[[error:invalid-data]]');
}
- const size = data.file ? data.file.size : image.sizeFromBase64(data.imageData);
+ const size = image.sizeFromBase64(data.imageData);
if (size > maxSize * 1024) {
throw new Error('[[error:file-too-big, ' + maxSize + ']]');
}
- const type = getMimeType(data);
+ const type = image.mimeFromBase64(data.imageData);
if (!type || !allowedTypes.includes(type)) {
throw new Error('[[error:invalid-image]]');
}
}
- function getMimeType(data) {
- return data.file ? data.file.type : image.mimeFromBase64(data.imageData);
- }
-
- async function getTempPath(data) {
- if (data.file) {
- return data.file.path;
- }
- return await image.writeImageDataToTempFile(data.imageData);
- }
-
async function convertToPNG(path) {
const convertToPNG = meta.config['profile:convertProfileImageToPNG'] === 1;
if (!convertToPNG) {
diff --git a/src/webserver.js b/src/webserver.js
index 3b2e0b8cd2..77f0d4b474 100644
--- a/src/webserver.js
+++ b/src/webserver.js
@@ -48,9 +48,9 @@ module.exports.app = app;
server.on('error', function (err) {
if (err.code === 'EADDRINUSE') {
- winston.error('NodeBB address in use, exiting...', err);
+ winston.error('NodeBB address in use, exiting...', err.stack);
} else {
- winston.error(err);
+ winston.error(err.stack);
}
throw err;
@@ -265,7 +265,7 @@ function listen(callback) {
oldUmask = process.umask('0000');
module.exports.testSocket(socketPath, function (err) {
if (err) {
- winston.error('[startup] NodeBB was unable to secure domain socket access (' + socketPath + ')', err);
+ winston.error('[startup] NodeBB was unable to secure domain socket access (' + socketPath + ')', err.stack);
throw err;
}
diff --git a/test/api.js b/test/api.js
index 92bdbe7358..15e3fded31 100644
--- a/test/api.js
+++ b/test/api.js
@@ -5,6 +5,8 @@ const path = require('path');
const SwaggerParser = require('@apidevtools/swagger-parser');
const request = require('request-promise-native');
const nconf = require('nconf');
+const util = require('util');
+const wait = util.promisify(setTimeout);
const db = require('./mocks/databasemock');
const helpers = require('./helpers');
@@ -15,6 +17,7 @@ const topics = require('../src/topics');
const plugins = require('../src/plugins');
const flags = require('../src/flags');
const messaging = require('../src/messaging');
+const socketUser = require('../src/socket.io/user');
describe('Read API', async () => {
let readApi = false;
@@ -58,6 +61,13 @@ describe('Read API', async () => {
// Create a new chat room
await messaging.newRoom(1, [2]);
+ // export data for admin user
+ await socketUser.exportProfile({ uid: adminUid }, { uid: adminUid });
+ await socketUser.exportPosts({ uid: adminUid }, { uid: adminUid });
+ await socketUser.exportUploads({ uid: adminUid }, { uid: adminUid });
+ // wait for export child process to complete
+ await wait(20000);
+
// Attach a search hook so /api/search is enabled
plugins.registerHook('core', {
hook: 'filter:search.query',
diff --git a/test/database/hash.js b/test/database/hash.js
index b6aba5852f..8d94a23b6b 100644
--- a/test/database/hash.js
+++ b/test/database/hash.js
@@ -435,6 +435,10 @@ describe('Hash methods', function () {
});
});
+ it('should not error if one of the fields is undefined', async function () {
+ await db.deleteObjectFields('someKey', ['best', undefined]);
+ });
+
it('should not error if field is null', function (done) {
db.deleteObjectField('someKey', null, function (err) {
assert.ifError(err);
diff --git a/test/file.js b/test/file.js
index 759bc55ac5..24aa655bed 100644
--- a/test/file.js
+++ b/test/file.js
@@ -96,6 +96,14 @@ describe('file', function () {
done();
});
});
+
+ it('should error if folder is relative', function (done) {
+ file.saveFileToLocal(filename, '../../text', tempPath + '000000000', function (err) {
+ assert(err);
+ assert.strictEqual(err.message, '[[error:invalid-path]]');
+ done();
+ });
+ });
});
it('should walk directory', function (done) {
diff --git a/test/helpers/index.js b/test/helpers/index.js
index 554ffb813c..f38ef8795c 100644
--- a/test/helpers/index.js
+++ b/test/helpers/index.js
@@ -107,7 +107,7 @@ helpers.uploadFile = function (uploadEndPoint, filePath, body, jar, csrf_token,
return callback(err);
}
if (res.statusCode !== 200) {
- winston.error(body);
+ winston.error(JSON.stringify(body));
}
callback(null, res, body);
});
diff --git a/test/uploads.js b/test/uploads.js
index 1fdef50ca4..ec8618f3f6 100644
--- a/test/uploads.js
+++ b/test/uploads.js
@@ -220,6 +220,13 @@ describe('Upload Controllers', function () {
});
});
+ it('should not allow non image uploads', function (done) {
+ socketUser.updateCover({ uid: 1 }, { uid: 1, file: { path: '../../text.txt' } }, function (err) {
+ assert.equal(err.message, '[[error:invalid-data]]');
+ done();
+ });
+ });
+
it('should not allow non image uploads', function (done) {
socketUser.updateCover({ uid: 1 }, { uid: 1, imageData: 'data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+' }, function (err) {
assert.equal(err.message, '[[error:invalid-image]]');
@@ -234,6 +241,13 @@ describe('Upload Controllers', function () {
});
});
+ it('should not allow non image uploads', function (done) {
+ socketUser.uploadCroppedPicture({ uid: 1 }, { uid: 1, file: { path: '../../text.txt' } }, function (err) {
+ assert.equal(err.message, '[[error:invalid-data]]');
+ done();
+ });
+ });
+
it('should not allow non image uploads', function (done) {
socketUser.uploadCroppedPicture({ uid: 1 }, { uid: 1, imageData: 'data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+' }, function (err) {
assert.equal(err.message, '[[error:invalid-image]]');
@@ -396,5 +410,33 @@ describe('Upload Controllers', function () {
});
});
});
+
+ it('should upload regular file', function (done) {
+ helpers.uploadFile(nconf.get('url') + '/api/admin/upload/file', path.join(__dirname, '../test/files/test.png'), {
+ params: JSON.stringify({
+ folder: 'system',
+ }),
+ }, jar, csrf_token, function (err, res, body) {
+ assert.ifError(err);
+ assert.equal(res.statusCode, 200);
+ assert(Array.isArray(body));
+ assert.equal(body[0].url, '/assets/uploads/system/test.png');
+ assert(file.existsSync(path.join(nconf.get('upload_path'), 'system', 'test.png')));
+ done();
+ });
+ });
+
+ it('should fail to upload regular file in wrong directory', function (done) {
+ helpers.uploadFile(nconf.get('url') + '/api/admin/upload/file', path.join(__dirname, '../test/files/test.png'), {
+ params: JSON.stringify({
+ folder: '../../system',
+ }),
+ }, jar, csrf_token, function (err, res, body) {
+ assert.ifError(err);
+ assert.equal(res.statusCode, 500);
+ assert.strictEqual(body.error, '[[error:invalid-path]]');
+ done();
+ });
+ });
});
});
diff --git a/test/user.js b/test/user.js
index fa0b271404..1e785c040a 100644
--- a/test/user.js
+++ b/test/user.js
@@ -100,6 +100,40 @@ describe('User', function () {
done();
});
});
+
+ it('should error if username is already taken', async function () {
+ let err;
+ async function tryCreate(data) {
+ try {
+ return await User.create(data);
+ } catch (_err) {
+ err = _err;
+ }
+ }
+
+ await Promise.all([
+ tryCreate({ username: 'dupe1' }),
+ tryCreate({ username: 'dupe1' }),
+ ]);
+ assert.strictEqual(err.message, '[[error:username-taken]]');
+ });
+
+ it('should error if email is already taken', async function () {
+ let err;
+ async function tryCreate(data) {
+ try {
+ return await User.create(data);
+ } catch (_err) {
+ err = _err;
+ }
+ }
+
+ await Promise.all([
+ tryCreate({ username: 'notdupe1', email: 'dupe@dupe.com' }),
+ tryCreate({ username: 'notdupe2', email: 'dupe@dupe.com' }),
+ ]);
+ assert.strictEqual(err.message, '[[error:email-taken]]');
+ });
});
describe('.uniqueUsername()', function () {
@@ -902,31 +936,6 @@ describe('User', function () {
});
});
- it('should upload profile picture', function (done) {
- helpers.copyFile(
- path.join(nconf.get('base_dir'), 'test/files/test.png'),
- path.join(nconf.get('base_dir'), 'test/files/test_copy.png'),
- function (err) {
- assert.ifError(err);
- var picture = {
- path: path.join(nconf.get('base_dir'), 'test/files/test_copy.png'),
- size: 7189,
- name: 'test_copy.png',
- type: 'image/png',
- };
- User.uploadCroppedPicture({
- uid: uid,
- file: picture,
- }, function (err, uploadedPicture) {
- assert.ifError(err);
- assert.equal(uploadedPicture.url, '/assets/uploads/profile/' + uid + '-profileavatar.png');
- assert.equal(uploadedPicture.path, path.join(nconf.get('upload_path'), 'profile', uid + '-profileavatar.png'));
- done();
- });
- }
- );
- });
-
it('should return error if profile image uploads disabled', function (done) {
meta.config.allowProfileImageUploads = 0;
var picture = {
@@ -940,37 +949,15 @@ describe('User', function () {
file: picture,
}, function (err) {
assert.equal(err.message, '[[error:profile-image-uploads-disabled]]');
- done();
- });
- });
-
- it('should return error if profile image is too big', function (done) {
- meta.config.allowProfileImageUploads = 1;
- var picture = {
- path: path.join(nconf.get('base_dir'), 'test/files/test_copy.png'),
- size: 265000,
- name: 'test.png',
- type: 'image/png',
- };
-
- User.uploadCroppedPicture({
- uid: uid,
- file: picture,
- }, function (err) {
- assert.equal(err.message, '[[error:file-too-big, 256]]');
+ meta.config.allowProfileImageUploads = 1;
done();
});
});
it('should return error if profile image has no mime type', function (done) {
- var picture = {
- path: path.join(nconf.get('base_dir'), 'test/files/test_copy.png'),
- size: 7189,
- name: 'test',
- };
User.uploadCroppedPicture({
uid: uid,
- file: picture,
+ imageData: 'data:image/invalid;base64,R0lGODlhPQBEAPeoAJosM/',
}, function (err) {
assert.equal(err.message, '[[error:invalid-image]]');
done();