mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-02 20:16:04 +01:00
Merge remote-tracking branch 'origin/master' into develop
This commit is contained in:
@@ -38,5 +38,11 @@
|
|||||||
"bookmarkThreshold": 5,
|
"bookmarkThreshold": 5,
|
||||||
"topicsPerList": 20,
|
"topicsPerList": 20,
|
||||||
"autoDetectLang": 1,
|
"autoDetectLang": 1,
|
||||||
"min:rep:flag": 0
|
"min:rep:flag": 0,
|
||||||
|
"notificationType_upvote": "notification",
|
||||||
|
"notificationType_new-topic": "notification",
|
||||||
|
"notificationType_new-reply": "notification",
|
||||||
|
"notificationType_follow": "notification",
|
||||||
|
"notificationType_new-chat": "notification",
|
||||||
|
"notificationType_group-invite": "notification"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,16 +70,5 @@
|
|||||||
"targetBlank": false,
|
"targetBlank": false,
|
||||||
"adminOnly": true
|
"adminOnly": true
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"route": "/search",
|
|
||||||
"title": "[[global:header.search]]",
|
|
||||||
"enabled": true,
|
|
||||||
"iconClass": "fa-search",
|
|
||||||
"textClass": "visible-xs-inline",
|
|
||||||
"text": "[[global:header.search]]",
|
|
||||||
"properties": {
|
|
||||||
"searchInstalled": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "nodebb",
|
"name": "nodebb",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"description": "NodeBB Forum",
|
"description": "NodeBB Forum",
|
||||||
"version": "1.7.4",
|
"version": "1.7.5",
|
||||||
"homepage": "http://www.nodebb.org",
|
"homepage": "http://www.nodebb.org",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
"body-parser": "^1.18.2",
|
"body-parser": "^1.18.2",
|
||||||
"bootstrap": "^3.3.7",
|
"bootstrap": "^3.3.7",
|
||||||
"chart.js": "^2.7.1",
|
"chart.js": "^2.7.1",
|
||||||
|
"clipboard": "1.7.1",
|
||||||
"colors": "^1.1.2",
|
"colors": "^1.1.2",
|
||||||
"compression": "^1.7.1",
|
"compression": "^1.7.1",
|
||||||
"commander": "^2.12.2",
|
"commander": "^2.12.2",
|
||||||
@@ -60,19 +61,19 @@
|
|||||||
"mousetrap": "^1.6.1",
|
"mousetrap": "^1.6.1",
|
||||||
"mubsub": "^1.4.0",
|
"mubsub": "^1.4.0",
|
||||||
"nconf": "^0.9.1",
|
"nconf": "^0.9.1",
|
||||||
"nodebb-plugin-composer-default": "6.0.12",
|
"nodebb-plugin-composer-default": "6.0.13",
|
||||||
"nodebb-plugin-dbsearch": "2.0.9",
|
"nodebb-plugin-dbsearch": "2.0.9",
|
||||||
"nodebb-plugin-emoji": "^2.1.0",
|
"nodebb-plugin-emoji": "^2.1.0",
|
||||||
"nodebb-plugin-emoji-android": "2.0.0",
|
"nodebb-plugin-emoji-android": "2.0.0",
|
||||||
"nodebb-plugin-markdown": "8.3.0",
|
"nodebb-plugin-markdown": "8.3.0",
|
||||||
"nodebb-plugin-mentions": "2.2.3",
|
"nodebb-plugin-mentions": "2.2.3",
|
||||||
"nodebb-plugin-soundpack-default": "1.0.0",
|
"nodebb-plugin-soundpack-default": "1.0.0",
|
||||||
"nodebb-plugin-spam-be-gone": "0.5.1",
|
"nodebb-plugin-spam-be-gone": "0.5.2",
|
||||||
"nodebb-rewards-essentials": "0.0.11",
|
"nodebb-rewards-essentials": "0.0.11",
|
||||||
"nodebb-theme-lavender": "5.0.1",
|
"nodebb-theme-lavender": "5.0.3",
|
||||||
"nodebb-theme-persona": "7.2.20",
|
"nodebb-theme-persona": "7.2.23",
|
||||||
"nodebb-theme-slick": "1.1.4",
|
"nodebb-theme-slick": "1.1.4",
|
||||||
"nodebb-theme-vanilla": "8.1.9",
|
"nodebb-theme-vanilla": "8.1.10",
|
||||||
"nodebb-widget-essentials": "4.0.2",
|
"nodebb-widget-essentials": "4.0.2",
|
||||||
"nodemailer": "4.4.1",
|
"nodemailer": "4.4.1",
|
||||||
"passport": "^0.4.0",
|
"passport": "^0.4.0",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"custom-css": "Custom CSS/LESS",
|
"custom-css": "Uživatelský CSS/LESS",
|
||||||
"custom-css.description": "Enter your own CSS/LESS declarations here, which will be applied after all other styles.",
|
"custom-css.description": "Zadejte vlastní definici CSS/LESS, která bude nadřazená ostatním stylům.",
|
||||||
"custom-css.enable": "Enable Custom CSS/LESS",
|
"custom-css.enable": "Povolit uživatelský CSS/LESS",
|
||||||
|
|
||||||
"custom-js": "Uživatelský Javascript",
|
"custom-js": "Uživatelský Javascript",
|
||||||
"custom-js.description": "Zadejte zde váš javascriptový kód. Bude spuštěn, jakmile se stránka plně načte.",
|
"custom-js.description": "Zadejte zde váš javascriptový kód. Bude spuštěn, jakmile se stránka plně načte.",
|
||||||
|
|||||||
@@ -4,5 +4,5 @@
|
|||||||
"home-page-route": "Cesta k domovské stránce",
|
"home-page-route": "Cesta k domovské stránce",
|
||||||
"custom-route": "Upravit cestu",
|
"custom-route": "Upravit cestu",
|
||||||
"allow-user-home-pages": "Povolit uživatelům domovské stránky",
|
"allow-user-home-pages": "Povolit uživatelům domovské stránky",
|
||||||
"home-page-title": "Title of the home page (default \"Home\")"
|
"home-page-title": "Titulka domovské stránky (výchozí „Domů”)"
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
"description": "Vyberte značky pomocí kliknutí a/nebo přetažením, pro vícenásobný výběr, použijte klávesu Shift.",
|
"description": "Vyberte značky pomocí kliknutí a/nebo přetažením, pro vícenásobný výběr, použijte klávesu Shift.",
|
||||||
"create": "Vytvořit značku",
|
"create": "Vytvořit značku",
|
||||||
"modify": "Upravit značky",
|
"modify": "Upravit značky",
|
||||||
"rename": "Rename Tags",
|
"rename": "Přejmenovat značky",
|
||||||
"delete": "Odstranit vybrané značky",
|
"delete": "Odstranit vybrané značky",
|
||||||
"search": "Hledat značky...",
|
"search": "Hledat značky...",
|
||||||
"settings": "Pro přejití na stránku s nastavením značek, klikněte <a href=\"%1\">zde</a>.",
|
"settings": "Pro přejití na stránku s nastavením značek, klikněte <a href=\"%1\">zde</a>.",
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
"remove-admin": "Odebrat správce",
|
"remove-admin": "Odebrat správce",
|
||||||
"validate-email": "Ověřit e-mail",
|
"validate-email": "Ověřit e-mail",
|
||||||
"send-validation-email": "Poslat ověřovací e-mail",
|
"send-validation-email": "Poslat ověřovací e-mail",
|
||||||
"password-reset-email": "Poslat e-mail pro resetování hesla",
|
"password-reset-email": "Poslat e-mail pro resetování hesla",
|
||||||
"ban": "Zakázat uživatele",
|
"ban": "Zakázat uživatele",
|
||||||
"temp-ban": "Dočasně zakázat uživatele",
|
"temp-ban": "Dočasně zakázat uživatele",
|
||||||
"unban": "Zrušit zákaz uživatele",
|
"unban": "Zrušit zákaz uživatele",
|
||||||
"reset-lockout": "Obnovit uzamčení",
|
"reset-lockout": "Obnovit uzamčení",
|
||||||
"reset-flags": "Obnovit označení",
|
"reset-flags": "Obnovit označení",
|
||||||
"delete": "Odstranit uživatele",
|
"delete": "Odstranit uživatele",
|
||||||
"purge": "Odstranit uživatele a obsah",
|
"purge": "Odstranit uživatele a obsah",
|
||||||
"download-csv": "Stáhnout jako CSV",
|
"download-csv": "Stáhnout jako CSV",
|
||||||
"invite": "Pozvat",
|
"invite": "Pozvat",
|
||||||
"new": "Nový uživatel",
|
"new": "Nový uživatel",
|
||||||
@@ -27,19 +27,19 @@
|
|||||||
"pills.banned": "Zakázán",
|
"pills.banned": "Zakázán",
|
||||||
"pills.search": "Hledat uživatele",
|
"pills.search": "Hledat uživatele",
|
||||||
|
|
||||||
"search.uid": "By User ID",
|
"search.uid": "Dle ID uživatele",
|
||||||
"search.uid-placeholder": "Enter a user ID to search",
|
"search.uid-placeholder": "Pro hledání, zadejte ID uživatele",
|
||||||
"search.username": "Dle jména uživatele",
|
"search.username": "Dle jména uživatele",
|
||||||
"search.username-placeholder": "Zadejte hledané uživatelské jméno",
|
"search.username-placeholder": "Zadejte hledané uživatelské jméno",
|
||||||
"search.email": "Podle e-mailu",
|
"search.email": "Podle e-mailu",
|
||||||
"search.email-placeholder": "Zadejte hledaný e-mail",
|
"search.email-placeholder": "Zadejte hledaný e-mail",
|
||||||
"search.ip": "Podle IP adresy",
|
"search.ip": "Podle IP adresy",
|
||||||
"search.ip-placeholder": "Zadejte hledanou IP adresu",
|
"search.ip-placeholder": "Zadejte hledanou IP adresu",
|
||||||
"search.not-found": "Uživatel nebyl nalezen.",
|
"search.not-found": "Uživatel nebyl nalezen.",
|
||||||
|
|
||||||
"inactive.3-months": "3 měsíce",
|
"inactive.3-months": "3 měsíce",
|
||||||
"inactive.6-months": "6 měsíců",
|
"inactive.6-months": "6 měsíců",
|
||||||
"inactive.12-months": "12 měsíců",
|
"inactive.12-months": "12 měsíců",
|
||||||
|
|
||||||
"users.uid": "uid",
|
"users.uid": "uid",
|
||||||
"users.username": "jméno",
|
"users.username": "jméno",
|
||||||
@@ -71,15 +71,15 @@
|
|||||||
"alerts.lockout-reset-success": "Uzamčení bylo obnoveno.",
|
"alerts.lockout-reset-success": "Uzamčení bylo obnoveno.",
|
||||||
"alerts.flag-reset-success": "Označení bylo obnoveno.",
|
"alerts.flag-reset-success": "Označení bylo obnoveno.",
|
||||||
"alerts.no-remove-yourself-admin": "Sebe jako správce nemůžete vyjmout.",
|
"alerts.no-remove-yourself-admin": "Sebe jako správce nemůžete vyjmout.",
|
||||||
"alerts.make-admin-success": "User is now administrator.",
|
"alerts.make-admin-success": "Uživatel je nyní správcem",
|
||||||
"alerts.confirm-remove-admin": "Do you really want to remove this administrator?",
|
"alerts.confirm-remove-admin": "Opravdu chcete vyjmout tohoto správce?",
|
||||||
"alerts.remove-admin-success": "User is no longer administrator.",
|
"alerts.remove-admin-success": "Uživatel již není správcem.",
|
||||||
"alerts.make-global-mod-success": "User is now global moderator.",
|
"alerts.make-global-mod-success": "Uživatel je nyní globálním moderátorem.",
|
||||||
"alerts.confirm-remove-global-mod": "Do you really want to remove this global moderator?",
|
"alerts.confirm-remove-global-mod": "Opravdu chcete vyjmout tohoto globálního moderátora?",
|
||||||
"alerts.remove-global-mod-success": "User is no longer global moderator.",
|
"alerts.remove-global-mod-success": "Uživatel již není globálním moderátorem.",
|
||||||
"alerts.make-moderator-success": "User is now moderator.",
|
"alerts.make-moderator-success": "Uživatel je nyní moderátorem.",
|
||||||
"alerts.confirm-remove-moderator": "Do you really want to remove this moderator?",
|
"alerts.confirm-remove-moderator": "Opravdu chcete vyjmout tohoto moderátora?",
|
||||||
"alerts.remove-moderator-success": "User is no longer moderator.",
|
"alerts.remove-moderator-success": "Uživatel není již moderátorem.",
|
||||||
"alerts.confirm-validate-email": "Chcete schválit e-mailové adresy těchto uživatelů?",
|
"alerts.confirm-validate-email": "Chcete schválit e-mailové adresy těchto uživatelů?",
|
||||||
"alerts.validate-email-success": "E-maily byly ověřeny",
|
"alerts.validate-email-success": "E-maily byly ověřeny",
|
||||||
"alerts.password-reset-confirm": "Chcete poslat těmto uživatelům e-mail pro resetování hesla?",
|
"alerts.password-reset-confirm": "Chcete poslat těmto uživatelům e-mail pro resetování hesla?",
|
||||||
@@ -95,5 +95,5 @@
|
|||||||
|
|
||||||
"alerts.prompt-email": "E-mail:",
|
"alerts.prompt-email": "E-mail:",
|
||||||
"alerts.email-sent-to": "E-mail s pozvánkou byl odeslán na %1",
|
"alerts.email-sent-to": "E-mail s pozvánkou byl odeslán na %1",
|
||||||
"alerts.x-users-found": "Počet nalezených uživatelů: %1 (hledání trvalo %2 ms)"
|
"alerts.x-users-found": "Počet nalezených uživatelů: %1 (hledání trvalo %2 ms)"
|
||||||
}
|
}
|
||||||
@@ -9,10 +9,10 @@
|
|||||||
|
|
||||||
"section-manage": "Spravovat",
|
"section-manage": "Spravovat",
|
||||||
"manage/categories": "Kategorie",
|
"manage/categories": "Kategorie",
|
||||||
"manage/privileges": "Privileges",
|
"manage/privileges": "Oprávnění",
|
||||||
"manage/tags": "Značky",
|
"manage/tags": "Značky",
|
||||||
"manage/users": "Uživatelé",
|
"manage/users": "Uživatelé",
|
||||||
"manage/admins-mods": "Admins & Mods",
|
"manage/admins-mods": "Správci a moderátoři",
|
||||||
"manage/registration": "Registrační fronta",
|
"manage/registration": "Registrační fronta",
|
||||||
"manage/post-queue": "Fronta příspěvků",
|
"manage/post-queue": "Fronta příspěvků",
|
||||||
"manage/groups": "Skupiny",
|
"manage/groups": "Skupiny",
|
||||||
@@ -70,8 +70,8 @@
|
|||||||
"search.placeholder": "Hledat nastavení",
|
"search.placeholder": "Hledat nastavení",
|
||||||
"search.no-results": "Žádné výsledky…",
|
"search.no-results": "Žádné výsledky…",
|
||||||
"search.search-forum": "Prohledat fórum pro <strong></strong>",
|
"search.search-forum": "Prohledat fórum pro <strong></strong>",
|
||||||
"search.keep-typing": "Pište dále pro zobrazení výsledků…",
|
"search.keep-typing": "Pište dále pro zobrazení výsledků…",
|
||||||
"search.start-typing": "Začněte psát pro zobrazení výsledků…",
|
"search.start-typing": "Začněte psát pro zobrazení výsledků…",
|
||||||
|
|
||||||
"connection-lost": "Připojení k %1 bylo ztraceno, snaha o opětovné připojení…"
|
"connection-lost": "Připojení k %1 bylo ztraceno, snaha o opětovné připojení…"
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,6 @@
|
|||||||
"max-length": "Maximální délka konverzační zprávy",
|
"max-length": "Maximální délka konverzační zprávy",
|
||||||
"max-room-size": "Maximální počet uživatelů v konverzační místnosti",
|
"max-room-size": "Maximální počet uživatelů v konverzační místnosti",
|
||||||
"delay": "Čas mezi konverzačními zprávami v milisekundách",
|
"delay": "Čas mezi konverzačními zprávami v milisekundách",
|
||||||
"restrictions.seconds-edit-after": "Number of seconds before users are allowed to edit chat messages after posting. (0 disabled)",
|
"restrictions.seconds-edit-after": "Počet sekund než je uživateli umožněno upravit zprávy konverzace po jejich odeslání. (0 zákaz)",
|
||||||
"restrictions.seconds-delete-after": "Number of seconds before users are allowed to delete chat messages after posting. (0 disabled)"
|
"restrictions.seconds-delete-after": "Počet sekund než je uživateli umožněno smazat zprávy konverzace po jejich odeslání. (0 zákaz)"
|
||||||
}
|
}
|
||||||
@@ -6,25 +6,25 @@
|
|||||||
"sorting.most-votes": "Dle počtu hlasů",
|
"sorting.most-votes": "Dle počtu hlasů",
|
||||||
"sorting.most-posts": "Dle počtu příspěvků",
|
"sorting.most-posts": "Dle počtu příspěvků",
|
||||||
"sorting.topic-default": "Výchozí třídění tématu",
|
"sorting.topic-default": "Výchozí třídění tématu",
|
||||||
"length": "Post Length",
|
"length": "Délka příspěvku",
|
||||||
"restrictions": "Omezení příspěvků",
|
"restrictions": "Omezení příspěvků",
|
||||||
"restrictions-new": "New User Restrictions",
|
"restrictions-new": "Omezení nového uživatele",
|
||||||
"restrictions.post-queue": "Povolit frontu pro příspěvky",
|
"restrictions.post-queue": "Povolit frontu pro příspěvky",
|
||||||
"restrictions-new.post-queue": "Enable new user restrictions",
|
"restrictions-new.post-queue": "Povolit omezení nových uživatelů",
|
||||||
"restrictions.post-queue-help": "Povolení fronty příspěvků bude přidávat příspěvky nových uživatelů do fronty na schválení.",
|
"restrictions.post-queue-help": "Povolení fronty příspěvků bude přidávat příspěvky nových uživatelů do fronty na schválení.",
|
||||||
"restrictions-new.post-queue-help": "Enabling new user restrictions will set restrictions on posts created by new users.",
|
"restrictions-new.post-queue-help": "Povolení omezení nových uživatelů uvede v činnost omezení na vytvořené příspěvky nových uživatelů.",
|
||||||
"restrictions.seconds-between": "Seconds between posts",
|
"restrictions.seconds-between": "Sekund mezi příspěvky",
|
||||||
"restrictions.seconds-between-new": "Seconds between posts for new users",
|
"restrictions.seconds-between-new": "Sekund mezi příspěvky pro nové uživatele",
|
||||||
"restrictions.rep-threshold": "Reputation threshold before these restrictions are lifted",
|
"restrictions.rep-threshold": "Ohraničení reputace než začnou platit tato omezení",
|
||||||
"restrictions.seconds-defore-new": "Sekundy předtím, než uživatel může přidat příspěvek",
|
"restrictions.seconds-defore-new": "Sekundy předtím, než uživatel může přidat příspěvek",
|
||||||
"restrictions.seconds-edit-after": "Number of seconds before users are allowed to edit posts after posting. (0 disabled)",
|
"restrictions.seconds-edit-after": "Počet sekund než bude moci uživatel upravit příspěvek před jeho odesláním. (0 zákaz)",
|
||||||
"restrictions.seconds-delete-after": "Number of seconds before users are allowed to delete posts after posting. (0 disabled)",
|
"restrictions.seconds-delete-after": "Počet sekund než bude moci uživatel smazat příspěvek před jeho odesláním. (0 zákaz)",
|
||||||
"restrictions.replies-no-delete": "Počet odpovědí, kdy je uživatelům zakázáno odstranit jejich vlastní příspěvek. (0 zakázáno)",
|
"restrictions.replies-no-delete": "Počet odpovědí, kdy je uživatelům zakázáno odstranit jejich vlastní příspěvek. (0 zakázáno)",
|
||||||
"restrictions.min-title-length": "Minimální délka názvu",
|
"restrictions.min-title-length": "Minimální délka názvu",
|
||||||
"restrictions.max-title-length": "Maximální délka názvu",
|
"restrictions.max-title-length": "Maximální délka názvu",
|
||||||
"restrictions.min-post-length": "Minimální délka příspěvku",
|
"restrictions.min-post-length": "Minimální délka příspěvku",
|
||||||
"restrictions.max-post-length": "Maximální délka příspěvku",
|
"restrictions.max-post-length": "Maximální délka příspěvku",
|
||||||
"restrictions.days-until-stale": "Days until topic is considered stale",
|
"restrictions.days-until-stale": "Počet dnů, než je téma považováno za neaktuální",
|
||||||
"restrictions.stale-help": "Je-li téma považováno za „staré”, uživateli se zobrazí oznámení při pokusu o přidání odpovědi.",
|
"restrictions.stale-help": "Je-li téma považováno za „staré”, uživateli se zobrazí oznámení při pokusu o přidání odpovědi.",
|
||||||
"timestamp": "Časový otisk",
|
"timestamp": "Časový otisk",
|
||||||
"timestamp.cut-off": "Datum ukončení (ve dnech)",
|
"timestamp.cut-off": "Datum ukončení (ve dnech)",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"thresholds": "Omezení aktivity",
|
"thresholds": "Omezení aktivity",
|
||||||
"min-rep-downvote": "Minimální reputace pro vyjádření nesouhlasu s příspěvkem",
|
"min-rep-downvote": "Minimální reputace pro vyjádření nesouhlasu s příspěvkem",
|
||||||
"min-rep-flag": "Minimální reputace pro označení příspěvků",
|
"min-rep-flag": "Minimální reputace pro označení příspěvků",
|
||||||
"min-rep-website": "Minimum reputation to add \"Website\" to user profile",
|
"min-rep-website": "Minimální reputace pro přidání „Webové stránky” do uživatelského profilu",
|
||||||
"min-rep-aboutme": "Minimum reputation to add \"About me\" to user profile",
|
"min-rep-aboutme": "Minimální reputace pro přidání „O mně” do uživatelského profilu",
|
||||||
"min-rep-signature": "Minimum reputation to add \"Signature\" to user profile"
|
"min-rep-signature": "Minimální reputace pro přidání „Podpisu” do uživatelského profilu"
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
"invalid-login-credentials": "Neplatné přihlašovací údaje",
|
"invalid-login-credentials": "Neplatné přihlašovací údaje",
|
||||||
"invalid-username-or-password": "Zadejte prosím uživatelské jméno a i heslo",
|
"invalid-username-or-password": "Zadejte prosím uživatelské jméno a i heslo",
|
||||||
"invalid-search-term": "Neplatný výraz pro vyhledávání",
|
"invalid-search-term": "Neplatný výraz pro vyhledávání",
|
||||||
"invalid-url": "Invalid URL",
|
"invalid-url": "Neplatné URL",
|
||||||
"csrf-invalid": "Není možné vás přihlásit, díky vypršení relace. Zkuste to prosím znovu.",
|
"csrf-invalid": "Není možné vás přihlásit, díky vypršení relace. Zkuste to prosím znovu.",
|
||||||
"invalid-pagination-value": "Neplatná hodnota stránkování, musí být alespoň %1 a nejvýše %2",
|
"invalid-pagination-value": "Neplatná hodnota stránkování, musí být alespoň %1 a nejvýše %2",
|
||||||
"username-taken": "Uživatelské jméno je již použito",
|
"username-taken": "Uživatelské jméno je již použito",
|
||||||
@@ -114,16 +114,16 @@
|
|||||||
"cant-edit-chat-message": "Tuto zprávu nemůžete upravit",
|
"cant-edit-chat-message": "Tuto zprávu nemůžete upravit",
|
||||||
"cant-remove-last-user": "Posledního uživatele nemůžete vyjmout",
|
"cant-remove-last-user": "Posledního uživatele nemůžete vyjmout",
|
||||||
"cant-delete-chat-message": "Tuto zprávu nemůžete odstranit",
|
"cant-delete-chat-message": "Tuto zprávu nemůžete odstranit",
|
||||||
"chat-edit-duration-expired": "You are only allowed to edit chat messages for %1 second(s) after posting",
|
"chat-edit-duration-expired": "Je vám umožněno upravit konverzační zprávy pod dobu %1 sekund/y po jejich odeslání",
|
||||||
"chat-delete-duration-expired": "You are only allowed to delete chat messages for %1 second(s) after posting",
|
"chat-delete-duration-expired": "Je vám umožněno odstranit konverzační zprávy pod dobu %1 sekund/y po jejich odeslání",
|
||||||
"already-voting-for-this-post": "Již jste v tomto příspěvku hlasoval.",
|
"already-voting-for-this-post": "Již jste v tomto příspěvku hlasoval.",
|
||||||
"reputation-system-disabled": "Systém reputací je zakázán.",
|
"reputation-system-disabled": "Systém reputací je zakázán.",
|
||||||
"downvoting-disabled": "Systém nesouhlasu je zakázán",
|
"downvoting-disabled": "Systém nesouhlasu je zakázán",
|
||||||
"not-enough-reputation-to-downvote": "Nemáte dostatečnou reputaci pro vyjádření nesouhlasu u tohoto příspěvku",
|
"not-enough-reputation-to-downvote": "Nemáte dostatečnou reputaci pro vyjádření nesouhlasu u tohoto příspěvku",
|
||||||
"not-enough-reputation-to-flag": "Pro označení tohoto příspěvku nemáte dostatečnou reputaci",
|
"not-enough-reputation-to-flag": "Pro označení tohoto příspěvku nemáte dostatečnou reputaci",
|
||||||
"not-enough-reputation-min-rep-website": "You do not have enough reputation to add a website",
|
"not-enough-reputation-min-rep-website": "Pro přidání webové stránky nemáte dostatek reputace",
|
||||||
"not-enough-reputation-min-rep-aboutme": "You do not have enough reputation to add an about me",
|
"not-enough-reputation-min-rep-aboutme": "Pro přidání „O mně” nemáte dostatek reputace",
|
||||||
"not-enough-reputation-min-rep-signature": "You do not have enough reputation to add a signature",
|
"not-enough-reputation-min-rep-signature": "Pro přidání podpisu nemáte dostatek reputace",
|
||||||
"already-flagged": "Tento příspěvek jste již označil",
|
"already-flagged": "Tento příspěvek jste již označil",
|
||||||
"self-vote": "U svého vlastního příspěvku nemůžete hlasovat",
|
"self-vote": "U svého vlastního příspěvku nemůžete hlasovat",
|
||||||
"reload-failed": "Vyskytla se chyba v NodeBB při znovu načtení: \"%1\". NodeBB bude pokračovat v běhu na straně klienta, nicméně byste měl/a přenastavit zpět to, co jste udělal/a před opětovným načtením.",
|
"reload-failed": "Vyskytla se chyba v NodeBB při znovu načtení: \"%1\". NodeBB bude pokračovat v běhu na straně klienta, nicméně byste měl/a přenastavit zpět to, co jste udělal/a před opětovným načtením.",
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
"topics": "Témata",
|
"topics": "Témata",
|
||||||
"posts": "Příspěvky",
|
"posts": "Příspěvky",
|
||||||
"best": "Nejlepší",
|
"best": "Nejlepší",
|
||||||
"votes": "Votes",
|
"votes": "Počet hlasů",
|
||||||
"upvoters": "Souhlasník",
|
"upvoters": "Souhlasník",
|
||||||
"upvoted": "Souhlasů",
|
"upvoted": "Souhlasů",
|
||||||
"downvoters": "Nesouhlasník",
|
"downvoters": "Nesouhlasník",
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
"language": "Jazyk",
|
"language": "Jazyk",
|
||||||
"guest": "Host",
|
"guest": "Host",
|
||||||
"guests": "Hosté",
|
"guests": "Hosté",
|
||||||
"updated.title": "Fórum zaktualizováno",
|
"updated.title": "Fórum bylo zaktualizováno",
|
||||||
"updated.message": "Toto fórum bylo právě aktualizováno na poslední verzi. Klikněte zde a obnovte tuto stránku.",
|
"updated.message": "Toto fórum bylo právě aktualizováno na poslední verzi. Klikněte zde a obnovte tuto stránku.",
|
||||||
"privacy": "Soukromí",
|
"privacy": "Soukromí",
|
||||||
"follow": "Sledovat",
|
"follow": "Sledovat",
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
"unsaved-changes": "Některé změny nebyly uloženy. Jste si jist, že chcete jít jinam?",
|
"unsaved-changes": "Některé změny nebyly uloženy. Jste si jist, že chcete jít jinam?",
|
||||||
"reconnecting-message": "Vypadá to, že vaše připojení k %1 bylo ukončeno. Vyčkejte prosím, než obnovíme připojení.",
|
"reconnecting-message": "Vypadá to, že vaše připojení k %1 bylo ukončeno. Vyčkejte prosím, než obnovíme připojení.",
|
||||||
"play": "Přehrát",
|
"play": "Přehrát",
|
||||||
"cookies.message": "Tato webová stránka používá \"cookies\", aby jste mohl plně zažít její funkčnost.",
|
"cookies.message": "Pro využití plné funkčnosti stránek, jsou použity „cookies”.",
|
||||||
"cookies.accept": "Rozumím.",
|
"cookies.accept": "Rozumím.",
|
||||||
"cookies.learn_more": "Zjistit více",
|
"cookies.learn_more": "Zjistit více",
|
||||||
"edited": "Upraveno",
|
"edited": "Upraveno",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"popular-month": "Oblíbená témata pro tento měsíc",
|
"popular-month": "Oblíbená témata pro tento měsíc",
|
||||||
"popular-alltime": "Oblíbená témata za celou dobu",
|
"popular-alltime": "Oblíbená témata za celou dobu",
|
||||||
"recent": "Aktuální témata",
|
"recent": "Aktuální témata",
|
||||||
"top": "Top Voted Topics",
|
"top": "Témata s nejvíce hlasy",
|
||||||
"moderator-tools": "Nástroje moderátora",
|
"moderator-tools": "Nástroje moderátora",
|
||||||
"flagged-content": "Nahlášený obsah",
|
"flagged-content": "Nahlášený obsah",
|
||||||
"ip-blacklist": "Černá listina IP adres",
|
"ip-blacklist": "Černá listina IP adres",
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
"users/search": "Hledat uživatele",
|
"users/search": "Hledat uživatele",
|
||||||
"notifications": "Upozornění",
|
"notifications": "Upozornění",
|
||||||
"tags": "Značky",
|
"tags": "Značky",
|
||||||
"tag": "Topics tagged under "%1"",
|
"tag": "Témata označená "%1"",
|
||||||
"register": "Zaregistrovat účet",
|
"register": "Zaregistrovat účet",
|
||||||
"registration-complete": "Registrace dokončena",
|
"registration-complete": "Registrace dokončena",
|
||||||
"login": "Přihlásit se ke svému účtu",
|
"login": "Přihlásit se ke svému účtu",
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
"flag_title": "Označit tento příspěvek k moderování",
|
"flag_title": "Označit tento příspěvek k moderování",
|
||||||
"deleted_message": "Toto téma bylo odstraněno. Jen uživatelé s oprávněním správy témat ho mohou vidět.",
|
"deleted_message": "Toto téma bylo odstraněno. Jen uživatelé s oprávněním správy témat ho mohou vidět.",
|
||||||
"following_topic.message": "Nyní budete dostávat upozornění, jakmile někdo přidá příspěvek do tohoto tématu.",
|
"following_topic.message": "Nyní budete dostávat upozornění, jakmile někdo přidá příspěvek do tohoto tématu.",
|
||||||
"not_following_topic.message": "Uvidíte toto téma v seznamu nepřečtených témat, ale neobdržíte upozornění. pokud sem někdo přidá příspěvek.",
|
"not_following_topic.message": " Toto téma uvidíte v seznamu nepřečtených témat, ale neobdržíte upozornění, přidá-li někdo nový příspěvek.",
|
||||||
"ignoring_topic.message": "Již nadále neuvidíte toto téma v seznamu nepřečtených témat. Budete upozorněn, jakmile se někdo o vás zmíní nebo bude vyjádřen souhlas s příspěvkem.",
|
"ignoring_topic.message": "Již nadále neuvidíte toto téma v seznamu nepřečtených témat. Budete upozorněn, jakmile se někdo o vás zmíní nebo bude vyjádřen souhlas s příspěvkem.",
|
||||||
"login_to_subscribe": "Pro sledování tohoto tématu se prosím přihlaste nebo zaregistrujte.",
|
"login_to_subscribe": "Pro sledování tohoto tématu se prosím přihlaste nebo zaregistrujte.",
|
||||||
"markAsUnreadForAll.success": "Téma označeno jako nepřečtené pro všechny.",
|
"markAsUnreadForAll.success": "Téma označeno jako nepřečtené pro všechny.",
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
"not-watching.description": "Neupozorňovat na nové odpovědi. <br/>Zobrazit téma v nepřečtených, není-li tato kategorie ignorována",
|
"not-watching.description": "Neupozorňovat na nové odpovědi. <br/>Zobrazit téma v nepřečtených, není-li tato kategorie ignorována",
|
||||||
"ignoring.description": "Neupozorňovat na nové odpovědi.<br/>Nezobrazovat téma v nepřečtených.",
|
"ignoring.description": "Neupozorňovat na nové odpovědi.<br/>Nezobrazovat téma v nepřečtených.",
|
||||||
"thread_tools.title": "Nástroje tématu",
|
"thread_tools.title": "Nástroje tématu",
|
||||||
"thread_tools.markAsUnreadForAll": "Mark Unread For All",
|
"thread_tools.markAsUnreadForAll": "Označit nepřečtené pro všechny",
|
||||||
"thread_tools.pin": "Připnout téma",
|
"thread_tools.pin": "Připnout téma",
|
||||||
"thread_tools.unpin": "Odepnout téma",
|
"thread_tools.unpin": "Odepnout téma",
|
||||||
"thread_tools.lock": "Zamknout téma",
|
"thread_tools.lock": "Zamknout téma",
|
||||||
|
|||||||
@@ -14,9 +14,6 @@
|
|||||||
"only-guest": "Only display to guests",
|
"only-guest": "Only display to guests",
|
||||||
"open-new-window": "Open in a new window",
|
"open-new-window": "Open in a new window",
|
||||||
|
|
||||||
"installed-plugins-required": "Installed Plugins Required:",
|
|
||||||
"search-plugin": "Search plugin",
|
|
||||||
|
|
||||||
"btn.delete": "Delete",
|
"btn.delete": "Delete",
|
||||||
"btn.disable": "Disable",
|
"btn.disable": "Disable",
|
||||||
"btn.enable": "Enable",
|
"btn.enable": "Enable",
|
||||||
|
|||||||
@@ -65,5 +65,7 @@
|
|||||||
"alert.find-user": "Find a User",
|
"alert.find-user": "Find a User",
|
||||||
"alert.user-search": "Search for a user here...",
|
"alert.user-search": "Search for a user here...",
|
||||||
"alert.find-group": "Find a Group",
|
"alert.find-group": "Find a Group",
|
||||||
"alert.group-search": "Search for a group here..."
|
"alert.group-search": "Search for a group here...",
|
||||||
|
"collapse-all": "Collapse All",
|
||||||
|
"expand-all": "Expand All"
|
||||||
}
|
}
|
||||||
@@ -14,5 +14,6 @@
|
|||||||
"alerts.applied-success": "Blacklist Applied",
|
"alerts.applied-success": "Blacklist Applied",
|
||||||
|
|
||||||
"analytics.blacklist-hourly": "<strong>Figure 1</strong> – Blacklist hits per hour",
|
"analytics.blacklist-hourly": "<strong>Figure 1</strong> – Blacklist hits per hour",
|
||||||
"analytics.blacklist-daily": "<strong>Figure 2</strong> – Blacklist hits per day"
|
"analytics.blacklist-daily": "<strong>Figure 2</strong> – Blacklist hits per day",
|
||||||
|
"ip-banned": "IP banned"
|
||||||
}
|
}
|
||||||
@@ -62,5 +62,6 @@
|
|||||||
"email-chat-notifs": "Send an email if a new chat message arrives and I am not online",
|
"email-chat-notifs": "Send an email if a new chat message arrives and I am not online",
|
||||||
"email-post-notif": "Send an email when replies are made to topics I am subscribed to",
|
"email-post-notif": "Send an email when replies are made to topics I am subscribed to",
|
||||||
"follow-created-topics": "Follow topics you create",
|
"follow-created-topics": "Follow topics you create",
|
||||||
"follow-replied-topics": "Follow topics that you reply to"
|
"follow-replied-topics": "Follow topics that you reply to",
|
||||||
|
"default-notification-settings": "Default notification settings"
|
||||||
}
|
}
|
||||||
@@ -161,6 +161,7 @@
|
|||||||
"wrong-login-type-email": "Please use your email to login",
|
"wrong-login-type-email": "Please use your email to login",
|
||||||
"wrong-login-type-username": "Please use your username to login",
|
"wrong-login-type-username": "Please use your username to login",
|
||||||
"sso-registration-disabled": "Registration has been disabled for %1 accounts, please register with an email address first",
|
"sso-registration-disabled": "Registration has been disabled for %1 accounts, please register with an email address first",
|
||||||
|
"sso-multiple-association": "You cannot associate multiple accounts from this service to your NodeBB account. Please dissociate your existing account and try again.",
|
||||||
|
|
||||||
"invite-maximum-met": "You have invited the maximum amount of people (%1 out of %2).",
|
"invite-maximum-met": "You have invited the maximum amount of people (%1 out of %2).",
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
"locked": "Locked",
|
"locked": "Locked",
|
||||||
"pinned": "Pinned",
|
"pinned": "Pinned",
|
||||||
"moved": "Moved",
|
"moved": "Moved",
|
||||||
|
"copy-ip": "Copy IP",
|
||||||
|
"ban-ip": "Ban IP",
|
||||||
|
|
||||||
"bookmark_instructions" : "Click here to return to the last read post in this thread.",
|
"bookmark_instructions" : "Click here to return to the last read post in this thread.",
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,7 @@
|
|||||||
"topics_per_page": "Topics per Page",
|
"topics_per_page": "Topics per Page",
|
||||||
"posts_per_page": "Posts per Page",
|
"posts_per_page": "Posts per Page",
|
||||||
"max_items_per_page": "Maximum %1",
|
"max_items_per_page": "Maximum %1",
|
||||||
|
"acp_language": "Admin Page Language",
|
||||||
"notification_sounds" : "Play a sound when you receive a notification",
|
"notification_sounds" : "Play a sound when you receive a notification",
|
||||||
"notifications_and_sounds": "Notifications & Sounds",
|
"notifications_and_sounds": "Notifications & Sounds",
|
||||||
"incoming-message-sound": "Incoming message sound",
|
"incoming-message-sound": "Incoming message sound",
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"figure-x": "Figure %1",
|
"figure-x": "Figure %1",
|
||||||
"error-events-per-day": "<code>%1</code> events per day",
|
"error-events-per-day": "<code>%1</code> events per day",
|
||||||
"error.404": "404 Not Found",
|
"error.404": "ارور 404 یافت نشد",
|
||||||
"error.503": "503 Service Unavailable",
|
"error.503": "ارور 503 سرویس دردسترس نیست",
|
||||||
"manage-error-log": "Manage Error Log",
|
"manage-error-log": "مدیریت Error Log",
|
||||||
"export-error-log": "Export Error Log (CSV)",
|
"export-error-log": "Export Error Log (CSV)",
|
||||||
"clear-error-log": "Clear Error Log",
|
"clear-error-log": "پاک کردن Error Log",
|
||||||
"route": "Route",
|
"route": "مسیر",
|
||||||
"count": "Count",
|
"count": "شمارش",
|
||||||
"no-routes-not-found": "Hooray! No 404 errors!",
|
"no-routes-not-found": "ایول! بدون ارور 404 !",
|
||||||
"clear404-confirm": "Are you sure you wish to clear the 404 error logs?",
|
"clear404-confirm": "آیا از پاک کردن ارور های 404 اطمینان دارید؟",
|
||||||
"clear404-success": "\"404 Not Found\" errors cleared"
|
"clear404-success": "ارور های 404 پاک شدند"
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"events": "Events",
|
"events": "رویداد ها",
|
||||||
"no-events": "There are no events",
|
"no-events": "رویدادی موجود نیست",
|
||||||
"control-panel": "Events Control Panel",
|
"control-panel": "کنترل پنل رویداد ها",
|
||||||
"delete-events": "Delete Events"
|
"delete-events": "پاک کردن رویداد ها"
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"logs": "Logs",
|
"logs": "گزارشات",
|
||||||
"control-panel": "Logs Control Panel",
|
"control-panel": "کنترل پنل گزارشات",
|
||||||
"reload": "Reload Logs",
|
"reload": "بارگزاری مجدد گزارش ها",
|
||||||
"clear": "Clear Logs",
|
"clear": "حذف گزارشات",
|
||||||
"clear-success": "Logs Cleared!"
|
"clear-success": "گزارش ها پاک شدند"
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"custom-css": "Custom CSS/LESS",
|
"custom-css": "سفارشی کردن CSS/LESS",
|
||||||
"custom-css.description": "Enter your own CSS/LESS declarations here, which will be applied after all other styles.",
|
"custom-css.description": "کد های CSS/LESS خود را در این قسمت وارد کنید . بعد از همه ی استایل های دیگر اعمال میشود",
|
||||||
"custom-css.enable": "Enable Custom CSS/LESS",
|
"custom-css.enable": "به کار گرفتن CSS/LESS سفارشی",
|
||||||
|
|
||||||
"custom-js": "Custom Javascript",
|
"custom-js": "جائا اسکریپت سفارشی",
|
||||||
"custom-js.description": "Enter your own javascript here. It will be executed after the page is loaded completely.",
|
"custom-js.description": "کد های جاوا اسکریپت خود را در این قسمت وارد کنید بعد از لود شدن تمام صفحه اجرا خواهند شد",
|
||||||
"custom-js.enable": "Enable Custom Javascript",
|
"custom-js.enable": "به کارگیری جاوا اسکریپت سفارشی ",
|
||||||
|
|
||||||
"custom-header": "Custom Header",
|
"custom-header": "هدر سفارشی",
|
||||||
"custom-header.description": "Enter custom HTML here (ex. Meta Tags, etc.), which will be appended to the <code><head></code> section of your forum's markup. Script tags are allowed, but are discouraged, as the <a href=\"#custom-header\" data-toggle=\"tab\">Custom Javascript</a> tab is available.",
|
"custom-header.description": "Enter custom HTML here (ex. Meta Tags, etc.), which will be appended to the <code><head></code> section of your forum's markup. Script tags are allowed, but are discouraged, as the <a href=\"#custom-header\" data-toggle=\"tab\">Custom Javascript</a> tab is available.",
|
||||||
"custom-header.enable": "Enable Custom Header",
|
"custom-header.enable": "Enable Custom Header",
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
"email_only": "فقط ایمیل",
|
"email_only": "فقط ایمیل",
|
||||||
"notification_and_email": "اعلان و ایمیل",
|
"notification_and_email": "اعلان و ایمیل",
|
||||||
"notificationType_upvote": "هنگامی که شخصی به پست شما رای مثبت می دهد",
|
"notificationType_upvote": "هنگامی که شخصی به پست شما رای مثبت می دهد",
|
||||||
"notificationType_new-topic": "هنگامی که شخصی که شما فالو می کنید موضوعی ایجاد نماید",
|
"notificationType_new-topic": "هنگامی که شخصی که شما دنبال می کنید موضوعی ایجاد نماید",
|
||||||
"notificationType_new-reply": "هنگامی که پاسخ جدید در تاپیکی که شما پیگیری می کنید فرستاده می شود",
|
"notificationType_new-reply": "هنگامی که پاسخ جدید در تاپیکی که شما پیگیری می کنید فرستاده می شود",
|
||||||
"notificationType_follow": "هنگامی که کسی شما را دنبال می کند",
|
"notificationType_follow": "هنگامی که کسی شما را دنبال می کند",
|
||||||
"notificationType_new-chat": "هنگامی که شما پیام چتی دریافت می کنید",
|
"notificationType_new-chat": "هنگامی که شما پیام چتی دریافت می کنید",
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
"topics": "Темы",
|
"topics": "Темы",
|
||||||
"posts": "Записи",
|
"posts": "Записи",
|
||||||
"best": "Лучшие",
|
"best": "Лучшие",
|
||||||
"votes": "Votes",
|
"votes": "Голоса",
|
||||||
"upvoters": "Кому понравилось",
|
"upvoters": "Кому понравилось",
|
||||||
"upvoted": "Понравилось",
|
"upvoted": "Понравилось",
|
||||||
"downvoters": "Кому не понравилось",
|
"downvoters": "Кому не понравилось",
|
||||||
@@ -105,6 +105,6 @@
|
|||||||
"cookies.accept": "Понял",
|
"cookies.accept": "Понял",
|
||||||
"cookies.learn_more": "Подробнее",
|
"cookies.learn_more": "Подробнее",
|
||||||
"edited": "Отредактированный",
|
"edited": "Отредактированный",
|
||||||
"disabled": "Disabled",
|
"disabled": "Отключено",
|
||||||
"select": "Select"
|
"select": "Выбрать"
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
"chat.three_months": "3 месяца",
|
"chat.three_months": "3 месяца",
|
||||||
"chat.delete_message_confirm": "Вы уверены, что хотите удалить это сообщение?",
|
"chat.delete_message_confirm": "Вы уверены, что хотите удалить это сообщение?",
|
||||||
"chat.add-users-to-room": "Добавить участников в комнату",
|
"chat.add-users-to-room": "Добавить участников в комнату",
|
||||||
"chat.confirm-chat-with-dnd-user": "This user has set their status to DnD(Do not disturb). Do you still want to chat with them?",
|
"chat.confirm-chat-with-dnd-user": "Этот пользователь установил статус \"Не беспокоить\". Вы все еще хотите написать ему?",
|
||||||
"composer.compose": "Редактор сообщений",
|
"composer.compose": "Редактор сообщений",
|
||||||
"composer.show_preview": "Показать предпросмотр сообщения",
|
"composer.show_preview": "Показать предпросмотр сообщения",
|
||||||
"composer.hide_preview": "Скрыть предпросмотр",
|
"composer.hide_preview": "Скрыть предпросмотр",
|
||||||
|
|||||||
@@ -6,11 +6,11 @@
|
|||||||
"popular-month": "Популярные темы этого месяца",
|
"popular-month": "Популярные темы этого месяца",
|
||||||
"popular-alltime": "Популярные темы за всё время",
|
"popular-alltime": "Популярные темы за всё время",
|
||||||
"recent": "Последние темы",
|
"recent": "Последние темы",
|
||||||
"top": "Top Voted Topics",
|
"top": "Самые популярные темы",
|
||||||
"moderator-tools": "Moderator Tools",
|
"moderator-tools": "Инструменты модератора",
|
||||||
"flagged-content": "Flagged Content",
|
"flagged-content": "Выбранное содержимое",
|
||||||
"ip-blacklist": "Чёрный список IP",
|
"ip-blacklist": "Чёрный список IP",
|
||||||
"post-queue": "Post Queue",
|
"post-queue": "Очередь публикации",
|
||||||
"users/online": "В сети",
|
"users/online": "В сети",
|
||||||
"users/latest": "Новые участники",
|
"users/latest": "Новые участники",
|
||||||
"users/sort-posts": "Участники по количеству сообщений",
|
"users/sort-posts": "Участники по количеству сообщений",
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
"users/search": "Поиск участников",
|
"users/search": "Поиск участников",
|
||||||
"notifications": "Уведомления",
|
"notifications": "Уведомления",
|
||||||
"tags": "Метки",
|
"tags": "Метки",
|
||||||
"tag": "Topics tagged under "%1"",
|
"tag": "Темы помеченные как "%1"",
|
||||||
"register": "Зарегистрироваться",
|
"register": "Зарегистрироваться",
|
||||||
"registration-complete": "Регистрация завершена",
|
"registration-complete": "Регистрация завершена",
|
||||||
"login": "Войти",
|
"login": "Войти",
|
||||||
@@ -30,8 +30,8 @@
|
|||||||
"group": "Группа %1",
|
"group": "Группа %1",
|
||||||
"chats": "Чаты",
|
"chats": "Чаты",
|
||||||
"chat": "Чат с участником %1",
|
"chat": "Чат с участником %1",
|
||||||
"flags": "Flags",
|
"flags": "Отметки",
|
||||||
"flag-details": "Flag %1 Details",
|
"flag-details": "Отметка %1 детали",
|
||||||
"account/edit": "Редактирование \"%1\"",
|
"account/edit": "Редактирование \"%1\"",
|
||||||
"account/edit/password": "Сменить пароль \"%1\"",
|
"account/edit/password": "Сменить пароль \"%1\"",
|
||||||
"account/edit/username": "Изменить имя пользователя \"%1\"",
|
"account/edit/username": "Изменить имя пользователя \"%1\"",
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
"account/bookmarks": "%1 сообщений в закладках",
|
"account/bookmarks": "%1 сообщений в закладках",
|
||||||
"account/settings": "Настройки учётной записи",
|
"account/settings": "Настройки учётной записи",
|
||||||
"account/watched": "Тему просмотрели %1",
|
"account/watched": "Тему просмотрели %1",
|
||||||
"account/ignored": "Topics ignored by %1",
|
"account/ignored": "Игнорируемые темы %1",
|
||||||
"account/upvoted": "Рейтинг записей поднят %1",
|
"account/upvoted": "Рейтинг записей поднят %1",
|
||||||
"account/downvoted": "Рейтинг записей снижен %1",
|
"account/downvoted": "Рейтинг записей снижен %1",
|
||||||
"account/best": "Лучшие записи участника %1",
|
"account/best": "Лучшие записи участника %1",
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
"not-watching.description": "Не уведомлять меня о новых ответах.<br/>Показать тему в непрочитанных, если категория мной не игнорируется.",
|
"not-watching.description": "Не уведомлять меня о новых ответах.<br/>Показать тему в непрочитанных, если категория мной не игнорируется.",
|
||||||
"ignoring.description": "Не уведомлять меня о новых ответах.<br/>Не отображать тему в непрочитанных.",
|
"ignoring.description": "Не уведомлять меня о новых ответах.<br/>Не отображать тему в непрочитанных.",
|
||||||
"thread_tools.title": "Настройки темы",
|
"thread_tools.title": "Настройки темы",
|
||||||
"thread_tools.markAsUnreadForAll": "Mark Unread For All",
|
"thread_tools.markAsUnreadForAll": "Выделить непрочитанные для всех",
|
||||||
"thread_tools.pin": "Прикрепить тему",
|
"thread_tools.pin": "Прикрепить тему",
|
||||||
"thread_tools.unpin": "Открепить тему",
|
"thread_tools.unpin": "Открепить тему",
|
||||||
"thread_tools.lock": "Закрыть тему",
|
"thread_tools.lock": "Закрыть тему",
|
||||||
@@ -68,8 +68,8 @@
|
|||||||
"thread_tools.restore_confirm": "Вы уверены, что хотите восстановить тему?",
|
"thread_tools.restore_confirm": "Вы уверены, что хотите восстановить тему?",
|
||||||
"thread_tools.purge": "Стереть тему",
|
"thread_tools.purge": "Стереть тему",
|
||||||
"thread_tools.purge_confirm": "Вы уверены, что хотите стереть эту тему?",
|
"thread_tools.purge_confirm": "Вы уверены, что хотите стереть эту тему?",
|
||||||
"thread_tools.merge_topics": "Merge Topics",
|
"thread_tools.merge_topics": "Объединить темы",
|
||||||
"thread_tools.merge": "Merge",
|
"thread_tools.merge": "Объединить",
|
||||||
"topic_move_success": "Эта тема успешно перемещена в %1",
|
"topic_move_success": "Эта тема успешно перемещена в %1",
|
||||||
"post_delete_confirm": "Вы уверены, что хотите удалить эту запись?",
|
"post_delete_confirm": "Вы уверены, что хотите удалить эту запись?",
|
||||||
"post_restore_confirm": "Вы уверены, что хотите восстановить эту запись?",
|
"post_restore_confirm": "Вы уверены, что хотите восстановить эту запись?",
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
"fork_pid_count": "Отмечено %1 сообщений",
|
"fork_pid_count": "Отмечено %1 сообщений",
|
||||||
"fork_success": "Готово! Просмотр отделённой темы.",
|
"fork_success": "Готово! Просмотр отделённой темы.",
|
||||||
"delete_posts_instruction": "Отметьте записи, которые вы хотите удалить",
|
"delete_posts_instruction": "Отметьте записи, которые вы хотите удалить",
|
||||||
"merge_topics_instruction": "Click the topics you want to merge",
|
"merge_topics_instruction": "Выберите темы которые вы хотите объединить",
|
||||||
"composer.title_placeholder": "Введите название темы...",
|
"composer.title_placeholder": "Введите название темы...",
|
||||||
"composer.handle_placeholder": "Название",
|
"composer.handle_placeholder": "Название",
|
||||||
"composer.discard": "Отменить",
|
"composer.discard": "Отменить",
|
||||||
|
|||||||
@@ -10,6 +10,6 @@
|
|||||||
"all-topics": "Все темы",
|
"all-topics": "Все темы",
|
||||||
"new-topics": "Новые темы",
|
"new-topics": "Новые темы",
|
||||||
"watched-topics": "Подписанные темы",
|
"watched-topics": "Подписанные темы",
|
||||||
"unreplied-topics": "Unreplied Topics",
|
"unreplied-topics": "Неотвеченные темы",
|
||||||
"multiple-categories-selected": "Multiple Selected"
|
"multiple-categories-selected": "Выбрано несколько"
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"reputation": "Репутация",
|
"reputation": "Репутация",
|
||||||
"bookmarks": "Закладки",
|
"bookmarks": "Закладки",
|
||||||
"watched": "Подписка",
|
"watched": "Подписка",
|
||||||
"ignored": "Ignored",
|
"ignored": "Игнорировать",
|
||||||
"followers": "Подписчиков",
|
"followers": "Подписчиков",
|
||||||
"following": "Подписок",
|
"following": "Подписок",
|
||||||
"aboutme": "Обо мне",
|
"aboutme": "Обо мне",
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
"chat": "Чат",
|
"chat": "Чат",
|
||||||
"chat_with": "Продолжить чат с %1",
|
"chat_with": "Продолжить чат с %1",
|
||||||
"new_chat_with": "Начать новый чат с %1",
|
"new_chat_with": "Начать новый чат с %1",
|
||||||
"flag-profile": "Flag Profile",
|
"flag-profile": "Идентификатор профиля",
|
||||||
"follow": "Подписаться",
|
"follow": "Подписаться",
|
||||||
"unfollow": "Отписаться",
|
"unfollow": "Отписаться",
|
||||||
"more": "Больше",
|
"more": "Больше",
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
"has_no_posts": "Участник пока не создал ни одной записи",
|
"has_no_posts": "Участник пока не создал ни одной записи",
|
||||||
"has_no_topics": "Участник пока не создал ни одной темы",
|
"has_no_topics": "Участник пока не создал ни одной темы",
|
||||||
"has_no_watched_topics": "Участник пока не посмотрел ни одной темы",
|
"has_no_watched_topics": "Участник пока не посмотрел ни одной темы",
|
||||||
"has_no_ignored_topics": "This user hasn't ignored any topics yet.",
|
"has_no_ignored_topics": "Этот пользователь еще не игнорировал ни одной темы.",
|
||||||
"has_no_upvoted_posts": "Участник пока не голосовал положительно ни за одну запись",
|
"has_no_upvoted_posts": "Участник пока не голосовал положительно ни за одну запись",
|
||||||
"has_no_downvoted_posts": "Участник пока не голосовал против ни одной записи",
|
"has_no_downvoted_posts": "Участник пока не голосовал против ни одной записи",
|
||||||
"has_no_voted_posts": "Участник пока не голосовал ни за одну запись",
|
"has_no_voted_posts": "Участник пока не голосовал ни за одну запись",
|
||||||
@@ -94,18 +94,18 @@
|
|||||||
"paginate_description": "Разбить на страницы, а не выводить бесконечным списком",
|
"paginate_description": "Разбить на страницы, а не выводить бесконечным списком",
|
||||||
"topics_per_page": "Тем на странице",
|
"topics_per_page": "Тем на странице",
|
||||||
"posts_per_page": "Записей на странице",
|
"posts_per_page": "Записей на странице",
|
||||||
"max_items_per_page": "Maximum %1",
|
"max_items_per_page": "Максимум %1",
|
||||||
"notification_sounds": "Воспроизводить звук во время получения уведомления",
|
"notification_sounds": "Воспроизводить звук во время получения уведомления",
|
||||||
"notifications_and_sounds": "Уведомления и звуки",
|
"notifications_and_sounds": "Уведомления и звуки",
|
||||||
"incoming-message-sound": "Звук входящего сообщения",
|
"incoming-message-sound": "Звук входящего сообщения",
|
||||||
"outgoing-message-sound": "Звук исходящего сообщения",
|
"outgoing-message-sound": "Звук исходящего сообщения",
|
||||||
"notification-sound": "Звук уведомления",
|
"notification-sound": "Звук уведомления",
|
||||||
"no-sound": "Без звука",
|
"no-sound": "Без звука",
|
||||||
"upvote-notif-freq": "Upvote Notification Frequency",
|
"upvote-notif-freq": "Частота уведомлений о понравившемся отзыве",
|
||||||
"upvote-notif-freq.all": "All Upvotes",
|
"upvote-notif-freq.all": "Все положительные отзывы",
|
||||||
"upvote-notif-freq.everyTen": "Every Ten Upvotes",
|
"upvote-notif-freq.everyTen": "Каждые десять понравившихся отзывов",
|
||||||
"upvote-notif-freq.logarithmic": "On 10, 100, 1000...",
|
"upvote-notif-freq.logarithmic": "На 10, 100, 1000...",
|
||||||
"upvote-notif-freq.disabled": "Disabled",
|
"upvote-notif-freq.disabled": "Выключено",
|
||||||
"browsing": "Настройки просмотра",
|
"browsing": "Настройки просмотра",
|
||||||
"open_links_in_new_tab": "Открывать внешние ссылки в новом окне",
|
"open_links_in_new_tab": "Открывать внешние ссылки в новом окне",
|
||||||
"enable_topic_searching": "Поиск во всех записях темы",
|
"enable_topic_searching": "Поиск во всех записях темы",
|
||||||
@@ -126,9 +126,9 @@
|
|||||||
"sso.title": "Для вашего удобства вы можете связать ваши учётные записи на других социальных сервисах с учётной записью на нашем сайте",
|
"sso.title": "Для вашего удобства вы можете связать ваши учётные записи на других социальных сервисах с учётной записью на нашем сайте",
|
||||||
"sso.associated": "Связан с",
|
"sso.associated": "Связан с",
|
||||||
"sso.not-associated": "Нажмите здесь, что бы связать учётную запись с",
|
"sso.not-associated": "Нажмите здесь, что бы связать учётную запись с",
|
||||||
"sso.dissociate": "Dissociate",
|
"sso.dissociate": "Открепить",
|
||||||
"sso.dissociate-confirm-title": "Confirm Dissociation",
|
"sso.dissociate-confirm-title": "Подтверждение открепления",
|
||||||
"sso.dissociate-confirm": "Are you sure you wish to dissociate your account from %1?",
|
"sso.dissociate-confirm": "Вы уверены, что хотите открепить свой аккаунт от %1?",
|
||||||
"info.latest-flags": "Новые отмеченные сообщения",
|
"info.latest-flags": "Новые отмеченные сообщения",
|
||||||
"info.no-flags": "Отмеченных сообщений не найдено",
|
"info.no-flags": "Отмеченных сообщений не найдено",
|
||||||
"info.ban-history": "Недавно заблокированы",
|
"info.ban-history": "Недавно заблокированы",
|
||||||
|
|||||||
@@ -37,6 +37,20 @@ define('admin/manage/categories', ['vendor/jquery/serializeObject/jquery.ba-seri
|
|||||||
el.find('i').toggleClass('fa-minus').toggleClass('fa-plus');
|
el.find('i').toggleClass('fa-minus').toggleClass('fa-plus');
|
||||||
el.closest('[data-cid]').find('> ul[data-cid]').toggleClass('hidden');
|
el.closest('[data-cid]').find('> ul[data-cid]').toggleClass('hidden');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#collapse-all').on('click', function () {
|
||||||
|
toggleAll(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#expand-all').on('click', function () {
|
||||||
|
toggleAll(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
function toggleAll(expand) {
|
||||||
|
var el = $('.categories .toggle');
|
||||||
|
el.find('i').toggleClass('fa-minus', expand).toggleClass('fa-plus', !expand);
|
||||||
|
el.closest('[data-cid]').find('> ul[data-cid]').toggleClass('hidden', !expand);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Categories.throwCreateModal = function () {
|
Categories.throwCreateModal = function () {
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ define('admin/settings', ['uploader'], function (uploader) {
|
|||||||
alert_id: 'config_status',
|
alert_id: 'config_status',
|
||||||
timeout: 2500,
|
timeout: 2500,
|
||||||
title: 'Changes Not Saved',
|
title: 'Changes Not Saved',
|
||||||
message: 'NodeBB encountered a problem saving your changes',
|
message: 'NodeBB encountered a problem saving your changes. (' + err.message + ')',
|
||||||
type: 'danger',
|
type: 'danger',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ define('forum/account/settings', ['forum/account/header', 'components', 'sounds'
|
|||||||
if (skinName === 'default') {
|
if (skinName === 'default') {
|
||||||
skinName = config.defaultBootswatchSkin;
|
skinName = config.defaultBootswatchSkin;
|
||||||
}
|
}
|
||||||
var cssSource = '//maxcdn.bootstrapcdn.com/bootswatch/latest/' + skinName + '/bootstrap.min.css';
|
var cssSource = '//maxcdn.bootstrapcdn.com/bootswatch/3.3.7/' + skinName + '/bootstrap.min.css';
|
||||||
if (css.length) {
|
if (css.length) {
|
||||||
css.attr('href', cssSource);
|
css.attr('href', cssSource);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ define('forum/topic', [
|
|||||||
var bookmarkKey = 'topic:' + ajaxify.data.tid + ':bookmark';
|
var bookmarkKey = 'topic:' + ajaxify.data.tid + ':bookmark';
|
||||||
var currentBookmark = ajaxify.data.bookmark || storage.getItem(bookmarkKey);
|
var currentBookmark = ajaxify.data.bookmark || storage.getItem(bookmarkKey);
|
||||||
|
|
||||||
if (ajaxify.data.postcount > ajaxify.data.bookmarkThreshold && (!currentBookmark || parseInt(index, 10) > parseInt(currentBookmark, 10))) {
|
if (ajaxify.data.postcount > ajaxify.data.bookmarkThreshold && (!currentBookmark || parseInt(index, 10) > parseInt(currentBookmark, 10) || ajaxify.data.postcount < parseInt(currentBookmark, 10))) {
|
||||||
if (app.user.uid) {
|
if (app.user.uid) {
|
||||||
socket.emit('topics.bookmark', {
|
socket.emit('topics.bookmark', {
|
||||||
tid: ajaxify.data.tid,
|
tid: ajaxify.data.tid,
|
||||||
|
|||||||
@@ -10,9 +10,6 @@ define('forum/topic/merge', function () {
|
|||||||
|
|
||||||
Merge.init = function () {
|
Merge.init = function () {
|
||||||
$('.category').on('click', '[component="topic/merge"]', onMergeTopicsClicked);
|
$('.category').on('click', '[component="topic/merge"]', onMergeTopicsClicked);
|
||||||
if (modal) {
|
|
||||||
$('[component="category/topic"]').on('click', 'a', onTopicClicked);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function onMergeTopicsClicked() {
|
function onMergeTopicsClicked() {
|
||||||
@@ -28,7 +25,7 @@ define('forum/topic/merge', function () {
|
|||||||
|
|
||||||
modal.find('.close,#merge_topics_cancel').on('click', closeModal);
|
modal.find('.close,#merge_topics_cancel').on('click', closeModal);
|
||||||
|
|
||||||
$('[component="category/topic"]').on('click', 'a', onTopicClicked);
|
$('[component="category"]').on('click', '[component="category/topic"] a', onTopicClicked);
|
||||||
|
|
||||||
showTopicsSelected();
|
showTopicsSelected();
|
||||||
|
|
||||||
@@ -40,15 +37,19 @@ define('forum/topic/merge', function () {
|
|||||||
|
|
||||||
function onTopicClicked(ev) {
|
function onTopicClicked(ev) {
|
||||||
var tid = $(this).parents('[component="category/topic"]').attr('data-tid');
|
var tid = $(this).parents('[component="category/topic"]').attr('data-tid');
|
||||||
var index = $(this).parents('[component="category/topic"]').attr('data-index');
|
socket.emit('topics.getTopic', tid, function (err, topicData) {
|
||||||
var title = ajaxify.data.topics[index] ? ajaxify.data.topics[index].title : 'No title';
|
if (err) {
|
||||||
if (selectedTids[tid]) {
|
return app.alertError(err);
|
||||||
delete selectedTids[tid];
|
}
|
||||||
} else {
|
var title = topicData ? topicData.title : 'No title';
|
||||||
selectedTids[tid] = title;
|
if (selectedTids[tid]) {
|
||||||
}
|
delete selectedTids[tid];
|
||||||
checkButtonEnable();
|
} else {
|
||||||
showTopicsSelected();
|
selectedTids[tid] = title;
|
||||||
|
}
|
||||||
|
checkButtonEnable();
|
||||||
|
showTopicsSelected();
|
||||||
|
});
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ define('forum/topic/postTools', [
|
|||||||
'translator',
|
'translator',
|
||||||
'forum/topic/votes',
|
'forum/topic/votes',
|
||||||
'forum/topic/move-post',
|
'forum/topic/move-post',
|
||||||
'benchpress',
|
], function (share, navigator, components, translator, votes, movePost) {
|
||||||
], function (share, navigator, components, translator, votes, movePost, Benchpress) {
|
|
||||||
var PostTools = {};
|
var PostTools = {};
|
||||||
|
|
||||||
var staleReplyAnyway = false;
|
var staleReplyAnyway = false;
|
||||||
@@ -45,11 +44,12 @@ define('forum/topic/postTools', [
|
|||||||
}
|
}
|
||||||
data.posts.display_move_tools = data.posts.display_move_tools && index !== 0;
|
data.posts.display_move_tools = data.posts.display_move_tools && index !== 0;
|
||||||
|
|
||||||
Benchpress.parse('partials/topic/post-menu-list', data, function (html) {
|
app.parseAndTranslate('partials/topic/post-menu-list', data, function (html) {
|
||||||
translator.translate(html, function (html) {
|
dropdownMenu.html(html);
|
||||||
dropdownMenu.html(html);
|
require(['clipboard'], function (clipboard) {
|
||||||
$(window).trigger('action:post.tools.load');
|
new clipboard('[data-clipboard-text]');
|
||||||
});
|
});
|
||||||
|
$(window).trigger('action:post.tools.load');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -192,6 +192,16 @@ define('forum/topic/postTools', [
|
|||||||
movePost.openMovePostModal($(this));
|
movePost.openMovePostModal($(this));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
postContainer.on('click', '[component="post/ban-ip"]', function () {
|
||||||
|
var ip = $(this).attr('data-ip');
|
||||||
|
socket.emit('blacklist.addRule', ip, function (err) {
|
||||||
|
if (err) {
|
||||||
|
return app.alertError(err.message);
|
||||||
|
}
|
||||||
|
app.alertSuccess('[[admin/manage/blacklist:ban-ip]]');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
postContainer.on('click', '[component="post/chat"]', function () {
|
postContainer.on('click', '[component="post/chat"]', function () {
|
||||||
openChat($(this));
|
openChat($(this));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -46,8 +46,7 @@
|
|||||||
if ((properties.loggedIn && !loggedIn) ||
|
if ((properties.loggedIn && !loggedIn) ||
|
||||||
(properties.guestOnly && loggedIn) ||
|
(properties.guestOnly && loggedIn) ||
|
||||||
(properties.globalMod && !data.isGlobalMod && !data.isAdmin) ||
|
(properties.globalMod && !data.isGlobalMod && !data.isAdmin) ||
|
||||||
(properties.adminOnly && !data.isAdmin) ||
|
(properties.adminOnly && !data.isAdmin)) {
|
||||||
(properties.searchInstalled && !data.searchEnabled)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ define('notifications', ['sounds', 'translator', 'components', 'navigator', 'ben
|
|||||||
payload.message = notifData.bodyShort;
|
payload.message = notifData.bodyShort;
|
||||||
payload.type = 'info';
|
payload.type = 'info';
|
||||||
payload.clickfn = function () {
|
payload.clickfn = function () {
|
||||||
if (notifData.path.startsWith('http') && notifData.path.startsWith('https')) {
|
if (notifData.path.startsWith('http') || notifData.path.startsWith('https')) {
|
||||||
window.location.href = notifData.path;
|
window.location.href = notifData.path;
|
||||||
} else {
|
} else {
|
||||||
window.location.href = window.location.protocol + '//' + window.location.host + config.relative_path + notifData.path;
|
window.location.href = window.location.protocol + '//' + window.location.host + config.relative_path + notifData.path;
|
||||||
|
|||||||
@@ -518,7 +518,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
tags: ['a', 'abbr', 'acronym', 'address', 'applet', 'area', 'article', 'aside', 'audio', 'b', 'base', 'basefont', 'bdi', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'command', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend', 'li', 'link', 'map', 'mark', 'menu', 'meta', 'meter', 'nav', 'noframes', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr'],
|
tags: ['a', 'abbr', 'acronym', 'address', 'applet', 'area', 'article', 'aside', 'audio', 'b', 'base', 'basefont',
|
||||||
|
'bdi', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup',
|
||||||
|
'command', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'em', 'embed',
|
||||||
|
'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
|
||||||
|
'head', 'header', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend', 'li', 'link',
|
||||||
|
'map', 'mark', 'menu', 'meta', 'meter', 'nav', 'noframes', 'noscript', 'object', 'ol', 'optgroup', 'option',
|
||||||
|
'output', 'p', 'param', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select',
|
||||||
|
'small', 'source', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot',
|
||||||
|
'th', 'thead', 'time', 'title', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr'],
|
||||||
|
|
||||||
stripTags: ['abbr', 'acronym', 'address', 'applet', 'area', 'article', 'aside', 'audio', 'base', 'basefont',
|
stripTags: ['abbr', 'acronym', 'address', 'applet', 'area', 'article', 'aside', 'audio', 'base', 'basefont',
|
||||||
'bdi', 'bdo', 'big', 'blink', 'body', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup',
|
'bdi', 'bdo', 'big', 'blink', 'body', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup',
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ module.exports = function (Categories) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
function (next) {
|
function (next) {
|
||||||
plugins.fireHook('filter:category.update', { category: modifiedFields }, next);
|
plugins.fireHook('filter:category.update', { cid: cid, category: modifiedFields }, next);
|
||||||
},
|
},
|
||||||
function (categoryData, next) {
|
function (categoryData, next) {
|
||||||
category = categoryData.category;
|
category = categoryData.category;
|
||||||
|
|||||||
@@ -41,11 +41,18 @@ function installAll() {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
cproc.execSync(command + (prod ? ' --production' : ''), {
|
cproc.execSync(command + (prod ? ' --production' : ''), {
|
||||||
cwd: path.join(__dirname, '../../'),
|
cwd: path.join(__dirname, '../../'),
|
||||||
stdio: [0, 1, 2],
|
stdio: [0, 1, 2],
|
||||||
});
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Error installing dependencies!');
|
||||||
|
console.log('message: ' + e.message);
|
||||||
|
console.log('stdout: ' + e.stdout);
|
||||||
|
console.log('stderr: ' + e.stderr);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.installAll = installAll;
|
exports.installAll = installAll;
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ function runSteps(tasks) {
|
|||||||
|
|
||||||
async.series(tasks, function (err) {
|
async.series(tasks, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error('Error occurred during upgrade');
|
console.error('Error occurred during upgrade: ' + err.stack);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
|
var _ = require('lodash');
|
||||||
|
|
||||||
var user = require('../../user');
|
var user = require('../../user');
|
||||||
var languages = require('../../languages');
|
var languages = require('../../languages');
|
||||||
@@ -40,6 +41,9 @@ settingsController.get = function (req, res, callback) {
|
|||||||
function (results, next) {
|
function (results, next) {
|
||||||
userData.settings = results.settings;
|
userData.settings = results.settings;
|
||||||
userData.languages = results.languages;
|
userData.languages = results.languages;
|
||||||
|
if (userData.isAdmin && userData.isSelf) {
|
||||||
|
userData.acpLanguages = _.cloneDeep(results.languages);
|
||||||
|
}
|
||||||
|
|
||||||
var types = [
|
var types = [
|
||||||
'notification',
|
'notification',
|
||||||
@@ -135,6 +139,12 @@ settingsController.get = function (req, res, callback) {
|
|||||||
language.selected = language.code === userData.settings.userLang;
|
language.selected = language.code === userData.settings.userLang;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (userData.isAdmin && userData.isSelf) {
|
||||||
|
userData.acpLanguages.forEach(function (language) {
|
||||||
|
language.selected = language.code === userData.settings.acpLang;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var notifFreqOptions = [
|
var notifFreqOptions = [
|
||||||
'all',
|
'all',
|
||||||
'everyTen',
|
'everyTen',
|
||||||
@@ -203,7 +213,7 @@ function getNotificationSettings(userData, callback) {
|
|||||||
},
|
},
|
||||||
function (results, next) {
|
function (results, next) {
|
||||||
function modifyType(type) {
|
function modifyType(type) {
|
||||||
var setting = userData.settings[type] || 'notification';
|
var setting = userData.settings[type];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: type,
|
name: type,
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ var analytics = require('../../analytics');
|
|||||||
var blacklistController = module.exports;
|
var blacklistController = module.exports;
|
||||||
|
|
||||||
blacklistController.get = function (req, res, next) {
|
blacklistController.get = function (req, res, next) {
|
||||||
// Analytics.getBlacklistAnalytics
|
|
||||||
async.parallel({
|
async.parallel({
|
||||||
rules: async.apply(meta.blacklist.get),
|
rules: async.apply(meta.blacklist.get),
|
||||||
analytics: async.apply(analytics.getBlacklistAnalytics),
|
analytics: async.apply(analytics.getBlacklistAnalytics),
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ apiController.loadConfig = function (req, callback) {
|
|||||||
config.topicsPerPage = settings.topicsPerPage;
|
config.topicsPerPage = settings.topicsPerPage;
|
||||||
config.postsPerPage = settings.postsPerPage;
|
config.postsPerPage = settings.postsPerPage;
|
||||||
config.userLang = (req.query.lang ? validator.escape(String(req.query.lang)) : null) || settings.userLang || config.defaultLang;
|
config.userLang = (req.query.lang ? validator.escape(String(req.query.lang)) : null) || settings.userLang || config.defaultLang;
|
||||||
|
config.acpLang = (req.query.lang ? validator.escape(String(req.query.lang)) : null) || settings.acpLang;
|
||||||
config.openOutgoingLinksInNewTab = settings.openOutgoingLinksInNewTab;
|
config.openOutgoingLinksInNewTab = settings.openOutgoingLinksInNewTab;
|
||||||
config.topicPostSort = settings.topicPostSort || config.topicPostSort;
|
config.topicPostSort = settings.topicPostSort || config.topicPostSort;
|
||||||
config.categoryTopicSort = settings.categoryTopicSort || config.categoryTopicSort;
|
config.categoryTopicSort = settings.categoryTopicSort || config.categoryTopicSort;
|
||||||
|
|||||||
@@ -233,6 +233,7 @@ Controllers.robots = function (req, res) {
|
|||||||
} else {
|
} else {
|
||||||
res.send('User-agent: *\n' +
|
res.send('User-agent: *\n' +
|
||||||
'Disallow: ' + nconf.get('relative_path') + '/admin/\n' +
|
'Disallow: ' + nconf.get('relative_path') + '/admin/\n' +
|
||||||
|
'Disallow: ' + nconf.get('relative_path') + '/reset/\n' +
|
||||||
'Sitemap: ' + nconf.get('url') + '/sitemap.xml');
|
'Sitemap: ' + nconf.get('url') + '/sitemap.xml');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
12
src/flags.js
12
src/flags.js
@@ -645,10 +645,18 @@ Flags.notify = function (flagObj, uid, callback) {
|
|||||||
admins: async.apply(groups.getMembers, 'administrators', 0, -1),
|
admins: async.apply(groups.getMembers, 'administrators', 0, -1),
|
||||||
globalMods: async.apply(groups.getMembers, 'Global Moderators', 0, -1),
|
globalMods: async.apply(groups.getMembers, 'Global Moderators', 0, -1),
|
||||||
moderators: function (next) {
|
moderators: function (next) {
|
||||||
|
var cid;
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
async.apply(posts.getCidByPid, flagObj.targetId),
|
async.apply(posts.getCidByPid, flagObj.targetId),
|
||||||
function (cid, next) {
|
function (_cid, next) {
|
||||||
groups.getMembers('cid:' + cid + ':privileges:moderate', 0, -1, next);
|
cid = _cid;
|
||||||
|
groups.getMembers('cid:' + cid + ':privileges:groups:moderate', 0, -1, next);
|
||||||
|
},
|
||||||
|
function (moderatorGroups, next) {
|
||||||
|
groups.getMembersOfGroups(moderatorGroups.concat(['cid:' + cid + ':privileges:moderate']), next);
|
||||||
|
},
|
||||||
|
function (members, next) {
|
||||||
|
next(null, _.flatten(members));
|
||||||
},
|
},
|
||||||
], next);
|
], next);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,13 +8,14 @@ var db = require('../database');
|
|||||||
|
|
||||||
module.exports = function (Groups) {
|
module.exports = function (Groups) {
|
||||||
Groups.create = function (data, callback) {
|
Groups.create = function (data, callback) {
|
||||||
var system = isSystemGroup(data);
|
var isSystem = isSystemGroup(data);
|
||||||
var groupData;
|
var groupData;
|
||||||
var timestamp = data.timestamp || Date.now();
|
var timestamp = data.timestamp || Date.now();
|
||||||
var disableJoinRequests = parseInt(data.disableJoinRequests, 10) === 1 ? 1 : 0;
|
var disableJoinRequests = parseInt(data.disableJoinRequests, 10) === 1 ? 1 : 0;
|
||||||
if (data.name === 'administrators') {
|
if (data.name === 'administrators') {
|
||||||
disableJoinRequests = 1;
|
disableJoinRequests = 1;
|
||||||
}
|
}
|
||||||
|
var isHidden = parseInt(data.hidden, 10) === 1;
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
validateGroupName(data.name, next);
|
validateGroupName(data.name, next);
|
||||||
@@ -38,8 +39,8 @@ module.exports = function (Groups) {
|
|||||||
description: data.description || '',
|
description: data.description || '',
|
||||||
memberCount: memberCount,
|
memberCount: memberCount,
|
||||||
deleted: 0,
|
deleted: 0,
|
||||||
hidden: parseInt(data.hidden, 10) === 1 ? 1 : 0,
|
hidden: isHidden ? 1 : 0,
|
||||||
system: system ? 1 : 0,
|
system: isSystem ? 1 : 0,
|
||||||
private: isPrivate,
|
private: isPrivate,
|
||||||
disableJoinRequests: disableJoinRequests,
|
disableJoinRequests: disableJoinRequests,
|
||||||
};
|
};
|
||||||
@@ -58,7 +59,7 @@ module.exports = function (Groups) {
|
|||||||
groupData.ownerUid = data.ownerUid;
|
groupData.ownerUid = data.ownerUid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data.hidden && !system) {
|
if (!isHidden && !isSystem) {
|
||||||
tasks.push(async.apply(db.sortedSetAdd, 'groups:visible:createtime', timestamp, groupData.name));
|
tasks.push(async.apply(db.sortedSetAdd, 'groups:visible:createtime', timestamp, groupData.name));
|
||||||
tasks.push(async.apply(db.sortedSetAdd, 'groups:visible:memberCount', groupData.memberCount, groupData.name));
|
tasks.push(async.apply(db.sortedSetAdd, 'groups:visible:memberCount', groupData.memberCount, groupData.name));
|
||||||
tasks.push(async.apply(db.sortedSetAdd, 'groups:visible:name', 0, groupData.name.toLowerCase() + ':' + groupData.name));
|
tasks.push(async.apply(db.sortedSetAdd, 'groups:visible:name', 0, groupData.name.toLowerCase() + ':' + groupData.name));
|
||||||
|
|||||||
@@ -71,12 +71,13 @@ Languages.list = function (callback) {
|
|||||||
if (err) {
|
if (err) {
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
|
var lang;
|
||||||
try {
|
try {
|
||||||
var lang = JSON.parse(file);
|
lang = JSON.parse(file);
|
||||||
next(null, lang);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
|
next(null, lang);
|
||||||
});
|
});
|
||||||
}, function (err, languages) {
|
}, function (err, languages) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|||||||
@@ -177,9 +177,44 @@ module.exports = function (Messaging) {
|
|||||||
}));
|
}));
|
||||||
db.sortedSetsRemove(keys, roomId, next);
|
db.sortedSetsRemove(keys, roomId, next);
|
||||||
},
|
},
|
||||||
|
function (next) {
|
||||||
|
updateOwner(roomId, next);
|
||||||
|
},
|
||||||
], callback);
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Messaging.leaveRooms = function (uid, roomIds, callback) {
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
var roomKeys = roomIds.map(function (roomId) {
|
||||||
|
return 'chat:room:' + roomId + ':uids';
|
||||||
|
});
|
||||||
|
db.sortedSetsRemove(roomKeys, uid, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
db.sortedSetRemove('uid:' + uid + ':chat:rooms', roomIds, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
db.sortedSetRemove('uid:' + uid + ':chat:rooms:unread', roomIds, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
async.eachSeries(roomIds, updateOwner, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
function updateOwner(roomId, callback) {
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
db.getSortedSetRange('chat:room:' + roomId + ':uids', 0, 0, next);
|
||||||
|
},
|
||||||
|
function (uids, next) {
|
||||||
|
var newOwner = uids[0] || 0;
|
||||||
|
db.setObjectField('chat:room:' + roomId, 'owner', newOwner, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
|
}
|
||||||
|
|
||||||
Messaging.getUidsInRoom = function (roomId, start, stop, callback) {
|
Messaging.getUidsInRoom = function (roomId, start, stop, callback) {
|
||||||
db.getSortedSetRevRange('chat:room:' + roomId + ':uids', start, stop, callback);
|
db.getSortedSetRevRange('chat:room:' + roomId + ':uids', start, stop, callback);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,9 +9,8 @@ var pubsub = require('../pubsub');
|
|||||||
var plugins = require('../plugins');
|
var plugins = require('../plugins');
|
||||||
var analytics = require('../analytics');
|
var analytics = require('../analytics');
|
||||||
|
|
||||||
var Blacklist = {
|
var Blacklist = module.exports;
|
||||||
_rules: [],
|
Blacklist._rules = [];
|
||||||
};
|
|
||||||
|
|
||||||
Blacklist.load = function (callback) {
|
Blacklist.load = function (callback) {
|
||||||
callback = callback || function () {};
|
callback = callback || function () {};
|
||||||
@@ -182,4 +181,22 @@ Blacklist.validate = function (rules, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Blacklist;
|
Blacklist.addRule = function (rule, callback) {
|
||||||
|
var valid;
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
Blacklist.validate(rule, next);
|
||||||
|
},
|
||||||
|
function (result, next) {
|
||||||
|
valid = result.valid;
|
||||||
|
if (!valid.length) {
|
||||||
|
return next(new Error('[[error:invalid-rule]]'));
|
||||||
|
}
|
||||||
|
Blacklist.get(next);
|
||||||
|
},
|
||||||
|
function (rules, next) {
|
||||||
|
rules = rules + '\n' + valid[0];
|
||||||
|
Blacklist.save(rules, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
var async = require('async');
|
var async = require('async');
|
||||||
var nconf = require('nconf');
|
var nconf = require('nconf');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
var winston = require('winston');
|
||||||
|
|
||||||
var db = require('../database');
|
var db = require('../database');
|
||||||
var pubsub = require('../pubsub');
|
var pubsub = require('../pubsub');
|
||||||
@@ -83,9 +84,17 @@ function processConfig(data, callback) {
|
|||||||
var image = require('../image');
|
var image = require('../image');
|
||||||
if (data['brand:logo']) {
|
if (data['brand:logo']) {
|
||||||
image.size(path.join(nconf.get('upload_path'), 'system', 'site-logo-x50.png'), function (err, size) {
|
image.size(path.join(nconf.get('upload_path'), 'system', 'site-logo-x50.png'), function (err, size) {
|
||||||
if (err) {
|
if (err && err.code === 'ENOENT') {
|
||||||
|
// For whatever reason the x50 logo wasn't generated, gracefully error out
|
||||||
|
winston.warn('[logo] The email-safe logo doesn\'t seem to have been created, please re-upload your site logo.');
|
||||||
|
size = {
|
||||||
|
height: 0,
|
||||||
|
width: 0,
|
||||||
|
};
|
||||||
|
} else if (err) {
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
data['brand:emailLogo:height'] = size.height;
|
data['brand:emailLogo:height'] = size.height;
|
||||||
data['brand:emailLogo:width'] = size.width;
|
data['brand:emailLogo:width'] = size.width;
|
||||||
next();
|
next();
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ JS.scripts = {
|
|||||||
'jqueryui.js': 'public/vendor/jquery/js/jquery-ui.js',
|
'jqueryui.js': 'public/vendor/jquery/js/jquery-ui.js',
|
||||||
'zxcvbn.js': 'node_modules/zxcvbn/dist/zxcvbn.js',
|
'zxcvbn.js': 'node_modules/zxcvbn/dist/zxcvbn.js',
|
||||||
ace: 'node_modules/ace-builds/src-min',
|
ace: 'node_modules/ace-builds/src-min',
|
||||||
|
'clipboard.js': 'node_modules/clipboard/dist/clipboard.min.js',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ module.exports = function (middleware) {
|
|||||||
plugins: [],
|
plugins: [],
|
||||||
authentication: [],
|
authentication: [],
|
||||||
};
|
};
|
||||||
|
res.locals.config = res.locals.config || {};
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
async.parallel({
|
async.parallel({
|
||||||
@@ -51,9 +51,6 @@ module.exports = function (middleware) {
|
|||||||
custom_header: function (next) {
|
custom_header: function (next) {
|
||||||
plugins.fireHook('filter:admin.header.build', custom_header, next);
|
plugins.fireHook('filter:admin.header.build', custom_header, next);
|
||||||
},
|
},
|
||||||
config: function (next) {
|
|
||||||
controllers.api.getConfig(req, res, next);
|
|
||||||
},
|
|
||||||
configs: function (next) {
|
configs: function (next) {
|
||||||
meta.configs.list(next);
|
meta.configs.list(next);
|
||||||
},
|
},
|
||||||
@@ -64,8 +61,6 @@ module.exports = function (middleware) {
|
|||||||
userData.uid = req.uid;
|
userData.uid = req.uid;
|
||||||
userData['email:confirmed'] = parseInt(userData['email:confirmed'], 10) === 1;
|
userData['email:confirmed'] = parseInt(userData['email:confirmed'], 10) === 1;
|
||||||
|
|
||||||
res.locals.config = results.config;
|
|
||||||
|
|
||||||
var acpPath = req.path.slice(1).split('/');
|
var acpPath = req.path.slice(1).split('/');
|
||||||
acpPath.forEach(function (path, i) {
|
acpPath.forEach(function (path, i) {
|
||||||
acpPath[i] = path.charAt(0).toUpperCase() + path.slice(1);
|
acpPath[i] = path.charAt(0).toUpperCase() + path.slice(1);
|
||||||
@@ -73,9 +68,9 @@ module.exports = function (middleware) {
|
|||||||
acpPath = acpPath.join(' > ');
|
acpPath = acpPath.join(' > ');
|
||||||
|
|
||||||
var templateValues = {
|
var templateValues = {
|
||||||
config: results.config,
|
config: res.locals.config,
|
||||||
configJSON: jsesc(JSON.stringify(results.config), { isScriptContext: true }),
|
configJSON: jsesc(JSON.stringify(res.locals.config), { isScriptContext: true }),
|
||||||
relative_path: results.config.relative_path,
|
relative_path: res.locals.config.relative_path,
|
||||||
adminConfigJSON: encodeURIComponent(JSON.stringify(results.configs)),
|
adminConfigJSON: encodeURIComponent(JSON.stringify(results.configs)),
|
||||||
user: userData,
|
user: userData,
|
||||||
userJSON: jsesc(JSON.stringify(userData), { isScriptContext: true }),
|
userJSON: jsesc(JSON.stringify(userData), { isScriptContext: true }),
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ module.exports = function (middleware) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (skinToUse) {
|
if (skinToUse) {
|
||||||
obj.bootswatchCSS = '//maxcdn.bootstrapcdn.com/bootswatch/latest/' + skinToUse + '/bootstrap.min.css';
|
obj.bootswatchCSS = '//maxcdn.bootstrapcdn.com/bootswatch/3.3.7/' + skinToUse + '/bootstrap.min.css';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -237,12 +237,18 @@ middleware.templatesOnDemand = function (req, res, next) {
|
|||||||
fs.readFile(filePath.replace(/\.js$/, '.tpl'), 'utf8', cb);
|
fs.readFile(filePath.replace(/\.js$/, '.tpl'), 'utf8', cb);
|
||||||
},
|
},
|
||||||
function (source, cb) {
|
function (source, cb) {
|
||||||
|
if (!source) {
|
||||||
|
return cb(new Error('[[error:templatesOnDemand.source-template-empty]]'));
|
||||||
|
}
|
||||||
Benchpress.precompile({
|
Benchpress.precompile({
|
||||||
source: source,
|
source: source,
|
||||||
minify: global.env !== 'development',
|
minify: global.env !== 'development',
|
||||||
}, cb);
|
}, cb);
|
||||||
},
|
},
|
||||||
function (compiled, cb) {
|
function (compiled, cb) {
|
||||||
|
if (!compiled) {
|
||||||
|
return cb(new Error('[[error:templatesOnDemand.compiled-template-empty]]'));
|
||||||
|
}
|
||||||
fs.writeFile(filePath, compiled, cb);
|
fs.writeFile(filePath, compiled, cb);
|
||||||
},
|
},
|
||||||
], function (err) {
|
], function (err) {
|
||||||
|
|||||||
@@ -41,8 +41,7 @@ module.exports = function (middleware) {
|
|||||||
options.template = { name: template };
|
options.template = { name: template };
|
||||||
options.template[template] = true;
|
options.template[template] = true;
|
||||||
options.url = (req.baseUrl + req.path.replace(/^\/api/, ''));
|
options.url = (req.baseUrl + req.path.replace(/^\/api/, ''));
|
||||||
options.bodyClass = buildBodyClass(req, options);
|
options.bodyClass = buildBodyClass(req, res, options);
|
||||||
|
|
||||||
plugins.fireHook('filter:' + template + '.build', { req: req, res: res, templateData: options }, next);
|
plugins.fireHook('filter:' + template + '.build', { req: req, res: res, templateData: options }, next);
|
||||||
},
|
},
|
||||||
function (data, next) {
|
function (data, next) {
|
||||||
@@ -120,13 +119,16 @@ module.exports = function (middleware) {
|
|||||||
|
|
||||||
function translate(str, req, res, next) {
|
function translate(str, req, res, next) {
|
||||||
var language = (res.locals.config && res.locals.config.userLang) || 'en-GB';
|
var language = (res.locals.config && res.locals.config.userLang) || 'en-GB';
|
||||||
|
if (res.locals.renderAdminHeader) {
|
||||||
|
language = (res.locals.config && res.locals.config.acpLang) || 'en-GB';
|
||||||
|
}
|
||||||
language = req.query.lang ? validator.escape(String(req.query.lang)) : language;
|
language = req.query.lang ? validator.escape(String(req.query.lang)) : language;
|
||||||
translator.translate(str, language, function (translated) {
|
translator.translate(str, language, function (translated) {
|
||||||
next(null, translator.unescape(translated));
|
next(null, translator.unescape(translated));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildBodyClass(req, templateData) {
|
function buildBodyClass(req, res, templateData) {
|
||||||
var clean = req.path.replace(/^\/api/, '').replace(/^\/|\/$/g, '');
|
var clean = req.path.replace(/^\/api/, '').replace(/^\/|\/$/g, '');
|
||||||
var parts = clean.split('/').slice(0, 3);
|
var parts = clean.split('/').slice(0, 3);
|
||||||
parts.forEach(function (p, index) {
|
parts.forEach(function (p, index) {
|
||||||
@@ -145,6 +147,7 @@ module.exports = function (middleware) {
|
|||||||
parts.push('page-topic-category-' + utils.slugify(templateData.category.name));
|
parts.push('page-topic-category-' + utils.slugify(templateData.category.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parts.push('page-status-' + res.statusCode);
|
||||||
return parts.join(' ');
|
return parts.join(' ');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -82,23 +82,20 @@ module.exports = function (Plugins) {
|
|||||||
|
|
||||||
var hookList = Plugins.loadedHooks[hook];
|
var hookList = Plugins.loadedHooks[hook];
|
||||||
var hookType = hook.split(':')[0];
|
var hookType = hook.split(':')[0];
|
||||||
try {
|
switch (hookType) {
|
||||||
switch (hookType) {
|
case 'filter':
|
||||||
case 'filter':
|
fireFilterHook(hook, hookList, params, callback);
|
||||||
fireFilterHook(hook, hookList, params, callback);
|
break;
|
||||||
break;
|
case 'action':
|
||||||
case 'action':
|
fireActionHook(hook, hookList, params, callback);
|
||||||
fireActionHook(hook, hookList, params, callback);
|
break;
|
||||||
break;
|
case 'static':
|
||||||
case 'static':
|
fireStaticHook(hook, hookList, params, callback);
|
||||||
fireStaticHook(hook, hookList, params, callback);
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
winston.warn('[plugins] Unknown hookType: ' + hookType + ', hook : ' + hook);
|
||||||
winston.warn('[plugins] Unknown hookType: ' + hookType + ', hook : ' + hook);
|
callback();
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
callback(err);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ function generateForTopic(req, res, callback) {
|
|||||||
var author = topicData.posts.length ? topicData.posts[0].username : '';
|
var author = topicData.posts.length ? topicData.posts[0].username : '';
|
||||||
|
|
||||||
var feed = new rss({
|
var feed = new rss({
|
||||||
title: utils.stripHTMLTags(topicData.title, utils.stripTags),
|
title: utils.stripHTMLTags(topicData.title, utils.tags),
|
||||||
description: description,
|
description: description,
|
||||||
feed_url: nconf.get('url') + '/topic/' + tid + '.rss',
|
feed_url: nconf.get('url') + '/topic/' + tid + '.rss',
|
||||||
site_url: nconf.get('url') + '/topic/' + topicData.slug,
|
site_url: nconf.get('url') + '/topic/' + topicData.slug,
|
||||||
@@ -125,7 +125,7 @@ function generateForTopic(req, res, callback) {
|
|||||||
dateStamp = new Date(parseInt(parseInt(postData.edited, 10) === 0 ? postData.timestamp : postData.edited, 10)).toUTCString();
|
dateStamp = new Date(parseInt(parseInt(postData.edited, 10) === 0 ? postData.timestamp : postData.edited, 10)).toUTCString();
|
||||||
|
|
||||||
feed.item({
|
feed.item({
|
||||||
title: 'Reply to ' + utils.stripHTMLTags(topicData.title, utils.stripTags) + ' on ' + dateStamp,
|
title: 'Reply to ' + utils.stripHTMLTags(topicData.title, utils.tags) + ' on ' + dateStamp,
|
||||||
description: postData.content,
|
description: postData.content,
|
||||||
url: nconf.get('url') + '/post/' + postData.pid,
|
url: nconf.get('url') + '/post/' + postData.pid,
|
||||||
author: postData.user ? postData.user.username : '',
|
author: postData.user ? postData.user.username : '',
|
||||||
@@ -301,7 +301,7 @@ function generateTopicsFeed(feedOptions, feedTopics, callback) {
|
|||||||
|
|
||||||
async.each(feedTopics, function (topicData, next) {
|
async.each(feedTopics, function (topicData, next) {
|
||||||
var feedItem = {
|
var feedItem = {
|
||||||
title: utils.stripHTMLTags(topicData.title, utils.stripTags),
|
title: utils.stripHTMLTags(topicData.title, utils.tags),
|
||||||
url: nconf.get('url') + '/topic/' + topicData.slug,
|
url: nconf.get('url') + '/topic/' + topicData.slug,
|
||||||
date: new Date(parseInt(topicData.lastposttime, 10)).toUTCString(),
|
date: new Date(parseInt(topicData.lastposttime, 10)).toUTCString(),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,3 +26,18 @@ SocketBlacklist.save = function (socket, rules, callback) {
|
|||||||
},
|
},
|
||||||
], callback);
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SocketBlacklist.addRule = function (socket, rule, callback) {
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
user.isAdminOrGlobalMod(socket.uid, next);
|
||||||
|
},
|
||||||
|
function (isAdminOrGlobalMod, next) {
|
||||||
|
if (!isAdminOrGlobalMod) {
|
||||||
|
return callback(new Error('[[error:no-privileges]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
meta.blacklist.addRule(rule, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
|
};
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ SocketHelpers.sendNotificationToPostOwner = function (pid, fromuid, command, not
|
|||||||
bodyShort: '[[' + notification + ', ' + results.username + ', ' + titleEscaped + ']]',
|
bodyShort: '[[' + notification + ', ' + results.username + ', ' + titleEscaped + ']]',
|
||||||
bodyLong: results.postObj.content,
|
bodyLong: results.postObj.content,
|
||||||
pid: pid,
|
pid: pid,
|
||||||
|
tid: postData.tid,
|
||||||
path: '/post/' + pid,
|
path: '/post/' + pid,
|
||||||
nid: command + ':post:' + pid + ':uid:' + fromuid,
|
nid: command + ':post:' + pid + ':uid:' + fromuid,
|
||||||
from: fromuid,
|
from: fromuid,
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ var socketTopics = require('../topics');
|
|||||||
var privileges = require('../../privileges');
|
var privileges = require('../../privileges');
|
||||||
var plugins = require('../../plugins');
|
var plugins = require('../../plugins');
|
||||||
var social = require('../../social');
|
var social = require('../../social');
|
||||||
|
var user = require('../../user');
|
||||||
|
|
||||||
|
|
||||||
module.exports = function (SocketPosts) {
|
module.exports = function (SocketPosts) {
|
||||||
SocketPosts.loadPostTools = function (socket, data, callback) {
|
SocketPosts.loadPostTools = function (socket, data, callback) {
|
||||||
@@ -20,10 +22,16 @@ module.exports = function (SocketPosts) {
|
|||||||
function (next) {
|
function (next) {
|
||||||
async.parallel({
|
async.parallel({
|
||||||
posts: function (next) {
|
posts: function (next) {
|
||||||
posts.getPostFields(data.pid, ['deleted', 'bookmarks', 'uid'], next);
|
posts.getPostFields(data.pid, ['deleted', 'bookmarks', 'uid', 'ip'], next);
|
||||||
},
|
},
|
||||||
isAdminOrMod: function (next) {
|
isAdmin: function (next) {
|
||||||
privileges.categories.isAdminOrMod(data.cid, socket.uid, next);
|
user.isAdministrator(socket.uid, next);
|
||||||
|
},
|
||||||
|
isGlobalMod: function (next) {
|
||||||
|
user.isGlobalModerator(socket.uid, next);
|
||||||
|
},
|
||||||
|
isModerator: function (next) {
|
||||||
|
user.isModerator(socket.uid, data.cid, next);
|
||||||
},
|
},
|
||||||
canEdit: function (next) {
|
canEdit: function (next) {
|
||||||
privileges.posts.canEdit(data.pid, socket.uid, next);
|
privileges.posts.canEdit(data.pid, socket.uid, next);
|
||||||
@@ -54,7 +62,12 @@ module.exports = function (SocketPosts) {
|
|||||||
results.posts.display_delete_tools = results.canDelete.flag;
|
results.posts.display_delete_tools = results.canDelete.flag;
|
||||||
results.posts.display_flag_tools = socket.uid && !results.posts.selfPost && results.canFlag.flag;
|
results.posts.display_flag_tools = socket.uid && !results.posts.selfPost && results.canFlag.flag;
|
||||||
results.posts.display_moderator_tools = results.posts.display_edit_tools || results.posts.display_delete_tools;
|
results.posts.display_moderator_tools = results.posts.display_edit_tools || results.posts.display_delete_tools;
|
||||||
results.posts.display_move_tools = results.isAdminOrMod;
|
results.posts.display_move_tools = results.isAdmin || results.isModerator;
|
||||||
|
results.posts.display_ip_ban = (results.isAdmin || results.isGlobalMod) && !results.posts.selfPost;
|
||||||
|
|
||||||
|
if (!results.isAdmin && !results.isGlobalMod && !results.isModerator) {
|
||||||
|
results.posts.ip = undefined;
|
||||||
|
}
|
||||||
next(null, results);
|
next(null, results);
|
||||||
},
|
},
|
||||||
], callback);
|
], callback);
|
||||||
|
|||||||
@@ -39,6 +39,13 @@ module.exports = function (SocketUser) {
|
|||||||
function (next) {
|
function (next) {
|
||||||
user.setUserFields(socket.uid, data, next);
|
user.setUserFields(socket.uid, data, next);
|
||||||
},
|
},
|
||||||
|
function (next) {
|
||||||
|
if (status !== 'offline') {
|
||||||
|
user.updateOnlineUsers(socket.uid, next);
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
},
|
||||||
function (next) {
|
function (next) {
|
||||||
var data = {
|
var data = {
|
||||||
uid: socket.uid,
|
uid: socket.uid,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
var async = require('async');
|
var async = require('async');
|
||||||
|
|
||||||
var db = require('../database');
|
var db = require('../database');
|
||||||
var posts = require('../posts');
|
var user = require('../user');
|
||||||
|
|
||||||
module.exports = function (Topics) {
|
module.exports = function (Topics) {
|
||||||
Topics.getUserBookmark = function (tid, uid, callback) {
|
Topics.getUserBookmark = function (tid, uid, callback) {
|
||||||
@@ -34,7 +34,9 @@ module.exports = function (Topics) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Topics.updateTopicBookmarks = function (tid, pids, callback) {
|
Topics.updateTopicBookmarks = function (tid, pids, callback) {
|
||||||
|
var minIndex;
|
||||||
var maxIndex;
|
var maxIndex;
|
||||||
|
var postIndices;
|
||||||
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
@@ -42,38 +44,54 @@ module.exports = function (Topics) {
|
|||||||
},
|
},
|
||||||
function (postcount, next) {
|
function (postcount, next) {
|
||||||
maxIndex = postcount;
|
maxIndex = postcount;
|
||||||
|
|
||||||
|
db.sortedSetRanks('tid:' + tid + ':posts', pids, next);
|
||||||
|
},
|
||||||
|
function (indices, next) {
|
||||||
|
postIndices = indices.map(function (i) {
|
||||||
|
return i === null ? 0 : i + 1;
|
||||||
|
});
|
||||||
|
minIndex = Math.min.apply(Math, postIndices);
|
||||||
|
|
||||||
Topics.getTopicBookmarks(tid, next);
|
Topics.getTopicBookmarks(tid, next);
|
||||||
},
|
},
|
||||||
function (bookmarks, next) {
|
function (bookmarks, next) {
|
||||||
var forkedPosts = pids.map(function (pid) {
|
|
||||||
return { pid: pid, tid: tid };
|
|
||||||
});
|
|
||||||
|
|
||||||
var uidData = bookmarks.map(function (bookmark) {
|
var uidData = bookmarks.map(function (bookmark) {
|
||||||
return {
|
return {
|
||||||
uid: bookmark.value,
|
uid: bookmark.value,
|
||||||
bookmark: bookmark.score,
|
bookmark: parseInt(bookmark.score, 10),
|
||||||
};
|
};
|
||||||
|
}).filter(function (data) {
|
||||||
|
return data.bookmark >= minIndex;
|
||||||
});
|
});
|
||||||
|
|
||||||
async.eachLimit(uidData, 50, function (data, next) {
|
async.eachLimit(uidData, 50, function (data, next) {
|
||||||
posts.getPostIndices(forkedPosts, data.uid, function (err, postIndices) {
|
var bookmark = data.bookmark;
|
||||||
|
bookmark = Math.min(bookmark, maxIndex);
|
||||||
|
|
||||||
|
postIndices.forEach(function (i) {
|
||||||
|
if (i < data.bookmark) {
|
||||||
|
bookmark -= 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// make sure the bookmark is valid if we removed the last post
|
||||||
|
bookmark = Math.min(bookmark, maxIndex - pids.length);
|
||||||
|
|
||||||
|
if (bookmark === data.bookmark) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
user.getSettings(data.uid, function (err, settings) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
var bookmark = data.bookmark;
|
if (settings.topicPostSort === 'most_votes') {
|
||||||
bookmark = bookmark < maxIndex ? bookmark : maxIndex;
|
return next();
|
||||||
|
|
||||||
for (var i = 0; i < postIndices.length && postIndices[i] < data.bookmark; i += 1) {
|
|
||||||
bookmark -= 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parseInt(bookmark, 10) !== parseInt(data.bookmark, 10)) {
|
Topics.setUserBookmark(tid, data.uid, bookmark, next);
|
||||||
Topics.setUserBookmark(tid, data.uid, bookmark, next);
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}, next);
|
}, next);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -209,18 +209,17 @@ module.exports = function (Topics) {
|
|||||||
var uid = data.uid;
|
var uid = data.uid;
|
||||||
var content = data.content;
|
var content = data.content;
|
||||||
var postData;
|
var postData;
|
||||||
var cid;
|
|
||||||
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
Topics.getTopicField(tid, 'cid', next);
|
Topics.getTopicField(tid, 'cid', next);
|
||||||
},
|
},
|
||||||
function (_cid, next) {
|
function (cid, next) {
|
||||||
cid = _cid;
|
data.cid = cid;
|
||||||
async.parallel({
|
async.parallel({
|
||||||
topicData: async.apply(Topics.getTopicData, tid),
|
topicData: async.apply(Topics.getTopicData, tid),
|
||||||
canReply: async.apply(privileges.topics.can, 'topics:reply', tid, uid),
|
canReply: async.apply(privileges.topics.can, 'topics:reply', tid, uid),
|
||||||
isAdminOrMod: async.apply(privileges.categories.isAdminOrMod, cid, uid),
|
isAdminOrMod: async.apply(privileges.categories.isAdminOrMod, data.cid, uid),
|
||||||
}, next);
|
}, next);
|
||||||
},
|
},
|
||||||
function (results, next) {
|
function (results, next) {
|
||||||
@@ -243,7 +242,7 @@ module.exports = function (Topics) {
|
|||||||
guestHandleValid(data, next);
|
guestHandleValid(data, next);
|
||||||
},
|
},
|
||||||
function (next) {
|
function (next) {
|
||||||
user.isReadyToPost(uid, cid, next);
|
user.isReadyToPost(uid, data.cid, next);
|
||||||
},
|
},
|
||||||
function (next) {
|
function (next) {
|
||||||
plugins.fireHook('filter:topic.reply', data, next);
|
plugins.fireHook('filter:topic.reply', data, next);
|
||||||
@@ -284,7 +283,7 @@ module.exports = function (Topics) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Topics.notifyFollowers(postData, uid);
|
Topics.notifyFollowers(postData, uid);
|
||||||
analytics.increment(['posts', 'posts:byCid:' + cid]);
|
analytics.increment(['posts', 'posts:byCid:' + data.cid]);
|
||||||
plugins.fireHook('action:topic.reply', { post: _.clone(postData) });
|
plugins.fireHook('action:topic.reply', { post: _.clone(postData) });
|
||||||
|
|
||||||
next(null, postData);
|
next(null, postData);
|
||||||
|
|||||||
@@ -33,7 +33,13 @@ Upgrade.getAll = function (callback) {
|
|||||||
versionA = path.dirname(a).split('/').pop();
|
versionA = path.dirname(a).split('/').pop();
|
||||||
versionB = path.dirname(b).split('/').pop();
|
versionB = path.dirname(b).split('/').pop();
|
||||||
|
|
||||||
return semver.compare(versionA, versionB);
|
var semverCompare = semver.compare(versionA, versionB);
|
||||||
|
if (semverCompare) {
|
||||||
|
return semverCompare;
|
||||||
|
}
|
||||||
|
var timestampA = require(a).timestamp;
|
||||||
|
var timestampB = require(b).timestamp;
|
||||||
|
return timestampA - timestampB;
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
async.apply(Upgrade.appendPluginScripts),
|
async.apply(Upgrade.appendPluginScripts),
|
||||||
|
|||||||
26
src/upgrades/1.7.6/notification_types.js
Normal file
26
src/upgrades/1.7.6/notification_types.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var async = require('async');
|
||||||
|
var db = require('../../database');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: 'Add default settings for notification delivery types',
|
||||||
|
timestamp: Date.UTC(2018, 1, 14),
|
||||||
|
method: function (callback) {
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
db.getObject('config', next);
|
||||||
|
},
|
||||||
|
function (config, next) {
|
||||||
|
db.setObject('config', {
|
||||||
|
notificationType_upvote: config.notificationType_upvote || 'notification',
|
||||||
|
'notificationType_new-topic': config['notificationType_new-topic'] || 'notification',
|
||||||
|
'notificationType_new-reply': config['notificationType_new-reply'] || config.sendPostNotifications || 'notification',
|
||||||
|
notificationType_follow: config.notificationType_follow || 'notification',
|
||||||
|
'notificationType_new-chat': config['notificationType_new-chat'] || config.sendChatNotifications || 'notification',
|
||||||
|
'notificationType_group-invite': config['notificationType_group-invite'] || 'notification',
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -7,6 +7,7 @@ var db = require('../database');
|
|||||||
var posts = require('../posts');
|
var posts = require('../posts');
|
||||||
var topics = require('../topics');
|
var topics = require('../topics');
|
||||||
var groups = require('../groups');
|
var groups = require('../groups');
|
||||||
|
var messaging = require('../messaging');
|
||||||
var plugins = require('../plugins');
|
var plugins = require('../plugins');
|
||||||
var batch = require('../batch');
|
var batch = require('../batch');
|
||||||
|
|
||||||
@@ -173,12 +174,9 @@ module.exports = function (User) {
|
|||||||
var userKeys = roomIds.map(function (roomId) {
|
var userKeys = roomIds.map(function (roomId) {
|
||||||
return 'uid:' + uid + ':chat:room:' + roomId + ':mids';
|
return 'uid:' + uid + ':chat:room:' + roomId + ':mids';
|
||||||
});
|
});
|
||||||
var roomKeys = roomIds.map(function (roomId) {
|
|
||||||
return 'chat:room:' + roomId + ':uids';
|
|
||||||
});
|
|
||||||
|
|
||||||
async.parallel([
|
async.parallel([
|
||||||
async.apply(db.sortedSetsRemove, roomKeys, uid),
|
async.apply(messaging.leaveRooms, uid, roomIds),
|
||||||
async.apply(db.deleteAll, userKeys),
|
async.apply(db.deleteAll, userKeys),
|
||||||
], next);
|
], next);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -126,14 +126,24 @@ UserEmail.sendValidationEmail = function (uid, options, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
UserEmail.confirm = function (code, callback) {
|
UserEmail.confirm = function (code, callback) {
|
||||||
|
var confirmObj;
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
db.getObject('confirm:' + code, next);
|
db.getObject('confirm:' + code, next);
|
||||||
},
|
},
|
||||||
function (confirmObj, next) {
|
function (_confirmObj, next) {
|
||||||
|
confirmObj = _confirmObj;
|
||||||
if (!confirmObj || !confirmObj.uid || !confirmObj.email) {
|
if (!confirmObj || !confirmObj.uid || !confirmObj.email) {
|
||||||
return next(new Error('[[error:invalid-data]]'));
|
return next(new Error('[[error:invalid-data]]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user.getUserField(confirmObj.uid, 'email', next);
|
||||||
|
},
|
||||||
|
function (currentEmail, next) {
|
||||||
|
if (!currentEmail || currentEmail.toLowerCase() !== confirmObj.email) {
|
||||||
|
return next(new Error('[[error:invalid-email]]'));
|
||||||
|
}
|
||||||
|
|
||||||
async.series([
|
async.series([
|
||||||
async.apply(user.setUserField, confirmObj.uid, 'email:confirmed', 1),
|
async.apply(user.setUserField, confirmObj.uid, 'email:confirmed', 1),
|
||||||
async.apply(db.delete, 'confirm:' + code),
|
async.apply(db.delete, 'confirm:' + code),
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ module.exports = function (User) {
|
|||||||
settings.topicsPerPage = Math.min(settings.topicsPerPage ? parseInt(settings.topicsPerPage, 10) : defaultTopicsPerPage, defaultTopicsPerPage);
|
settings.topicsPerPage = Math.min(settings.topicsPerPage ? parseInt(settings.topicsPerPage, 10) : defaultTopicsPerPage, defaultTopicsPerPage);
|
||||||
settings.postsPerPage = Math.min(settings.postsPerPage ? parseInt(settings.postsPerPage, 10) : defaultPostsPerPage, defaultPostsPerPage);
|
settings.postsPerPage = Math.min(settings.postsPerPage ? parseInt(settings.postsPerPage, 10) : defaultPostsPerPage, defaultPostsPerPage);
|
||||||
settings.userLang = settings.userLang || meta.config.defaultLang || 'en-GB';
|
settings.userLang = settings.userLang || meta.config.defaultLang || 'en-GB';
|
||||||
|
settings.acpLang = settings.acpLang || settings.userLang;
|
||||||
settings.topicPostSort = getSetting(settings, 'topicPostSort', 'oldest_to_newest');
|
settings.topicPostSort = getSetting(settings, 'topicPostSort', 'oldest_to_newest');
|
||||||
settings.categoryTopicSort = getSetting(settings, 'categoryTopicSort', 'newest_to_oldest');
|
settings.categoryTopicSort = getSetting(settings, 'categoryTopicSort', 'newest_to_oldest');
|
||||||
settings.followTopicsOnCreate = parseInt(getSetting(settings, 'followTopicsOnCreate', 1), 10) === 1;
|
settings.followTopicsOnCreate = parseInt(getSetting(settings, 'followTopicsOnCreate', 1), 10) === 1;
|
||||||
@@ -80,6 +81,12 @@ module.exports = function (User) {
|
|||||||
settings.delayImageLoading = parseInt(getSetting(settings, 'delayImageLoading', 1), 10) === 1;
|
settings.delayImageLoading = parseInt(getSetting(settings, 'delayImageLoading', 1), 10) === 1;
|
||||||
settings.bootswatchSkin = settings.bootswatchSkin || meta.config.bootswatchSkin || 'default';
|
settings.bootswatchSkin = settings.bootswatchSkin || meta.config.bootswatchSkin || 'default';
|
||||||
settings.scrollToMyPost = parseInt(getSetting(settings, 'scrollToMyPost', 1), 10) === 1;
|
settings.scrollToMyPost = parseInt(getSetting(settings, 'scrollToMyPost', 1), 10) === 1;
|
||||||
|
settings.notificationType_upvote = getSetting(settings, 'notificationType_upvote', 'notification');
|
||||||
|
settings['notificationType_new-topic'] = getSetting(settings, 'notificationType_new-topic', 'notification');
|
||||||
|
settings['notificationType_new-reply'] = getSetting(settings, 'notificationType_new-reply', 'notification');
|
||||||
|
settings.notificationType_follow = getSetting(settings, 'notificationType_follow', 'notification');
|
||||||
|
settings['notificationType_new-chat'] = getSetting(settings, 'notificationType_new-chat', 'notification');
|
||||||
|
settings['notificationType_group-invite'] = getSetting(settings, 'notificationType_group-invite', 'notification');
|
||||||
next(null, settings);
|
next(null, settings);
|
||||||
},
|
},
|
||||||
], callback);
|
], callback);
|
||||||
@@ -118,6 +125,7 @@ module.exports = function (User) {
|
|||||||
topicsPerPage: Math.min(data.topicsPerPage, parseInt(maxTopicsPerPage, 10) || 20),
|
topicsPerPage: Math.min(data.topicsPerPage, parseInt(maxTopicsPerPage, 10) || 20),
|
||||||
postsPerPage: Math.min(data.postsPerPage, parseInt(maxPostsPerPage, 10) || 20),
|
postsPerPage: Math.min(data.postsPerPage, parseInt(maxPostsPerPage, 10) || 20),
|
||||||
userLang: data.userLang || meta.config.defaultLang,
|
userLang: data.userLang || meta.config.defaultLang,
|
||||||
|
acpLang: data.acpLang || meta.config.defaultLang,
|
||||||
followTopicsOnCreate: data.followTopicsOnCreate,
|
followTopicsOnCreate: data.followTopicsOnCreate,
|
||||||
followTopicsOnReply: data.followTopicsOnReply,
|
followTopicsOnReply: data.followTopicsOnReply,
|
||||||
restrictChat: data.restrictChat,
|
restrictChat: data.restrictChat,
|
||||||
|
|||||||
@@ -91,15 +91,6 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<strong>[[admin/general/navigation:installed-plugins-required]]</strong>
|
|
||||||
|
|
||||||
<div class="checkbox">
|
|
||||||
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
|
||||||
<input class="mdl-switch__input" type="checkbox" name="property:searchInstalled" <!-- IF enabled.properties.searchInstalled -->checked<!-- ENDIF enabled.properties.searchInstalled -->/>
|
|
||||||
<span class="mdl-switch__label"><strong>[[admin/general/navigation:search-plugin]]</strong></span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button class="btn btn-danger delete">[[admin/general/navigation:btn.delete]]</button>
|
<button class="btn btn-danger delete">[[admin/general/navigation:btn.delete]]</button>
|
||||||
<!-- IF enabled.enabled -->
|
<!-- IF enabled.enabled -->
|
||||||
<button class="btn btn-warning toggle">[[admin/general/navigation:btn.disable]]</button>
|
<button class="btn btn-warning toggle">[[admin/general/navigation:btn.disable]]</button>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<button id="collapse-all" class="btn btn-default">[[admin/manage/categories:collapse-all]]</button> <button id="expand-all" class="btn btn-default">[[admin/manage/categories:expand-all]]</button>
|
||||||
|
<hr/>
|
||||||
<div class="categories"></div>
|
<div class="categories"></div>
|
||||||
|
|
||||||
<button data-action="create" class="floating-button mdl-button mdl-js-button mdl-button--fab mdl-js-ripple-effect mdl-button--colored">
|
<button data-action="create" class="floating-button mdl-button mdl-js-button mdl-button--fab mdl-js-ripple-effect mdl-button--colored">
|
||||||
|
|||||||
@@ -232,7 +232,6 @@
|
|||||||
<div class="col-sm-2 col-xs-12 settings-header">[[admin/settings/user:default-user-settings]]</div>
|
<div class="col-sm-2 col-xs-12 settings-header">[[admin/settings/user:default-user-settings]]</div>
|
||||||
<div class="col-sm-10 col-xs-12">
|
<div class="col-sm-10 col-xs-12">
|
||||||
<form>
|
<form>
|
||||||
|
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||||
<input class="mdl-switch__input" type="checkbox" data-field="showemail">
|
<input class="mdl-switch__input" type="checkbox" data-field="showemail">
|
||||||
@@ -292,6 +291,85 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<label>[[admin/settings/user:default-notification-settings]]</label>
|
||||||
|
<div class="row">
|
||||||
|
<div class="form-group col-xs-7">
|
||||||
|
<label>[[notifications:notificationType_upvote]]</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-group col-xs-5">
|
||||||
|
<select class="form-control" data-field="notificationType_upvote">
|
||||||
|
<option value="none">[[notifications:none]]</option>
|
||||||
|
<option value="notification">[[notifications:notification_only]]</option>
|
||||||
|
<option value="email">[[notifications:email_only]]</option>
|
||||||
|
<option value="notificationemail">[[notifications:notification_and_email]]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="form-group col-xs-7">
|
||||||
|
<label>[[notifications:notificationType_new-topic]]</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-group col-xs-5">
|
||||||
|
<select class="form-control" data-field="notificationType_new-topic">
|
||||||
|
<option value="none">[[notifications:none]]</option>
|
||||||
|
<option value="notification">[[notifications:notification_only]]</option>
|
||||||
|
<option value="email">[[notifications:email_only]]</option>
|
||||||
|
<option value="notificationemail">[[notifications:notification_and_email]]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="form-group col-xs-7">
|
||||||
|
<label>[[notifications:notificationType_new-reply]]</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-group col-xs-5">
|
||||||
|
<select class="form-control" data-field="notificationType_new-reply">
|
||||||
|
<option value="none">[[notifications:none]]</option>
|
||||||
|
<option value="notification">[[notifications:notification_only]]</option>
|
||||||
|
<option value="email">[[notifications:email_only]]</option>
|
||||||
|
<option value="notificationemail">[[notifications:notification_and_email]]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="form-group col-xs-7">
|
||||||
|
<label>[[notifications:notificationType_follow]]</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-group col-xs-5">
|
||||||
|
<select class="form-control" data-field="notificationType_follow">
|
||||||
|
<option value="none">[[notifications:none]]</option>
|
||||||
|
<option value="notification">[[notifications:notification_only]]</option>
|
||||||
|
<option value="email">[[notifications:email_only]]</option>
|
||||||
|
<option value="notificationemail">[[notifications:notification_and_email]]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="form-group col-xs-7">
|
||||||
|
<label>[[notifications:notificationType_new-chat]]</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-group col-xs-5">
|
||||||
|
<select class="form-control" data-field="notificationType_new-chat">
|
||||||
|
<option value="none">[[notifications:none]]</option>
|
||||||
|
<option value="notification">[[notifications:notification_only]]</option>
|
||||||
|
<option value="email">[[notifications:email_only]]</option>
|
||||||
|
<option value="notificationemail">[[notifications:notification_and_email]]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="form-group col-xs-7">
|
||||||
|
<label>[[notifications:notificationType_group-invite]]</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-group col-xs-5">
|
||||||
|
<select class="form-control" data-field="notificationType_group-invite">
|
||||||
|
<option value="none">[[notifications:none]]</option>
|
||||||
|
<option value="notification">[[notifications:notification_only]]</option>
|
||||||
|
<option value="email">[[notifications:email_only]]</option>
|
||||||
|
<option value="notificationemail">[[notifications:notification_and_email]]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -265,6 +265,47 @@ describe('Groups', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should create a hidden group if hidden is 1', function (done) {
|
||||||
|
Groups.create({
|
||||||
|
name: 'hidden group',
|
||||||
|
hidden: '1',
|
||||||
|
}, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
db.isSortedSetMember('groups:visible:memberCount', 'visible group', function (err, isMember) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(!isMember);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create a visible group if hidden is 0', function (done) {
|
||||||
|
Groups.create({
|
||||||
|
name: 'visible group',
|
||||||
|
hidden: '0',
|
||||||
|
}, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
db.isSortedSetMember('groups:visible:memberCount', 'visible group', function (err, isMember) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(isMember);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create a visible group if hidden is not passed in', function (done) {
|
||||||
|
Groups.create({
|
||||||
|
name: 'visible group 2',
|
||||||
|
}, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
db.isSortedSetMember('groups:visible:memberCount', 'visible group 2', function (err, isMember) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(isMember);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should fail to create group with duplicate group name', function (done) {
|
it('should fail to create group with duplicate group name', function (done) {
|
||||||
Groups.create({ name: 'foo' }, function (err) {
|
Groups.create({ name: 'foo' }, function (err) {
|
||||||
assert(err);
|
assert(err);
|
||||||
|
|||||||
@@ -177,7 +177,48 @@ describe('Messaging Library', function () {
|
|||||||
Messaging.isUserInRoom(bazUid, roomId, function (err, isUserInRoom) {
|
Messaging.isUserInRoom(bazUid, roomId, function (err, isUserInRoom) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.equal(isUserInRoom, false);
|
assert.equal(isUserInRoom, false);
|
||||||
done();
|
Messaging.getRoomData(roomId, function (err, data) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(data.owner, fooUid);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should change owner when owner leaves room', function (done) {
|
||||||
|
socketModules.chats.newRoom({ uid: herpUid }, { touid: fooUid }, function (err, roomId) {
|
||||||
|
assert.ifError(err);
|
||||||
|
socketModules.chats.addUserToRoom({ uid: herpUid }, { roomId: roomId, username: 'baz' }, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
socketModules.chats.leave({ uid: herpUid }, roomId, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
Messaging.getRoomData(roomId, function (err, data) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(data.owner, fooUid);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should change owner if owner is deleted', function (done) {
|
||||||
|
User.create({ username: 'deleted_chat_user' }, function (err, sender) {
|
||||||
|
assert.ifError(err);
|
||||||
|
User.create({ username: 'receiver' }, function (err, receiver) {
|
||||||
|
assert.ifError(err);
|
||||||
|
socketModules.chats.newRoom({ uid: sender }, { touid: receiver }, function (err, roomId) {
|
||||||
|
assert.ifError(err);
|
||||||
|
User.deleteAccount(sender, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
Messaging.getRoomData(roomId, function (err, data) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(data.owner, receiver);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ describe('Notifications', function () {
|
|||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
user.notifications.getAll(uid, 'post', function (err, nids) {
|
user.notifications.getAll(uid, 'post', function (err, nids) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.notEqual(nids.indexOf(nid), -1);
|
assert(nids.includes(nid));
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
}, 1500);
|
}, 1500);
|
||||||
|
|||||||
@@ -70,22 +70,6 @@ describe('Plugins', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not crash if there is an exception in a hook', function (done) {
|
|
||||||
function filterMethod(data, callback) {
|
|
||||||
var crash;
|
|
||||||
crash.a = 5;
|
|
||||||
callback(null, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
plugins.registerHook('test-plugin-crash', { hook: 'filter:test.crashHook', method: filterMethod });
|
|
||||||
|
|
||||||
plugins.fireHook('filter:test.crashHook', { foo: 1 }, function (err, data) {
|
|
||||||
assert(err);
|
|
||||||
assert.equal(err.message, 'Cannot set property \'a\' of undefined');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should get plugin data from nbbpm', function (done) {
|
it('should get plugin data from nbbpm', function (done) {
|
||||||
plugins.get('nodebb-plugin-markdown', function (err, data) {
|
plugins.get('nodebb-plugin-markdown', function (err, data) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
|||||||
Reference in New Issue
Block a user