diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 6b86318c16..ff56a966b5 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -79,7 +79,7 @@ Deprecations rule of thumb: After adding a new module to core, you need to do the following: 1. Update the `Dockerfile.phpdoc` file to include the new module classes folder (this generates our [PHPDoc](https://phpdoc.namelessmc.com/) site) 2. Update `composer.json` to autoload the new module classes folder -3. Add a new term to the `custom/languages/en_UK.json` file for the module description to be shown during instal +3. Add a new term to the `modules/Core/language/en_UK.json` file for the module description to be shown during instal - The term should be in the format `module_{module_name}_description` - Don't forget to add it to the `WHITELISTED_TERMS` array in `dev/scripts/find_unused_language_terms.sh` 4. Create new database entry to install it by default diff --git a/README.md b/README.md index 6cf4102bb7..6d2faa85a0 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ The following list is a brief summary of the features available in v2: - ✨ Pretty URL option (requires mod_rewrite or special nginx config). - 🎛 Widgets: allows modules to create widgets which can be displayed on most user-facing pages and display almost anything. - ⏳ Queue: schedule tasks to happen at a certain point in the future -- 🚩 Translated into [over 20 languages](https://github.com/NamelessMC/Nameless/tree/v2/custom/languages) +- 🚩 Translated into [over 20 languages](https://github.com/NamelessMC/Nameless/tree/v2/modules/Core/language) #### Customising Nameless diff --git a/core/classes/Core/Language.php b/core/classes/Core/Language.php index 7b71b4045c..c1cba01cc0 100644 --- a/core/classes/Core/Language.php +++ b/core/classes/Core/Language.php @@ -199,7 +199,7 @@ public function __construct(string $module = 'core', string $active_language = n // Require file if ($module === 'core') { - $path = implode(DIRECTORY_SEPARATOR, [ROOT_PATH, 'custom', 'languages', '__lng__.json']); + $path = implode(DIRECTORY_SEPARATOR, [ROOT_PATH, 'modules', 'Core', 'language', '__lng__.json']); } else { $path = str_replace('/', DIRECTORY_SEPARATOR, $module) . DIRECTORY_SEPARATOR . '__lng__.json'; } diff --git a/core/classes/Core/Validate.php b/core/classes/Core/Validate.php index 29dbf0572c..b8439ac303 100644 --- a/core/classes/Core/Validate.php +++ b/core/classes/Core/Validate.php @@ -96,6 +96,11 @@ class Validate { */ public const NOT_START_WITH = 'not_start_with'; + /** + * @var string Check that the value does not contain a pattern + */ + public const NOT_CONTAIN = 'not_contain'; + /** * @var string Set a rate limit */ @@ -365,6 +370,24 @@ public static function check(array $source, array $items = []): Validate { } break; + case self::NOT_CONTAIN: + if (!is_array($rule_value)) { + $rule_value = [$rule_value]; + } + + foreach ($rule_value as $term) { + if (strpos(strtolower($value), strtolower($term)) !== false) { + $validator->addError([ + 'field' => $item, + 'rule' => self::NOT_CONTAIN, + 'fallback' => "$item must not contain $term", + ]); + break; + } + } + + break; + case self::IN: $values = is_string($rule_value) ? [$rule_value] : $rule_value; if (!in_array($value, $values)) { diff --git a/core/classes/Endpoints/Endpoints.php b/core/classes/Endpoints/Endpoints.php index e2bc1f09f7..b3615ccf3b 100644 --- a/core/classes/Endpoints/Endpoints.php +++ b/core/classes/Endpoints/Endpoints.php @@ -1,4 +1,5 @@ throwError(Nameless2API::ERROR_INVALID_API_METHOD, "The $route endpoint only accepts " . implode(', ', $available_methods) . ", $method was used.", 405); + $api->throwError(Nameless2API::ERROR_INVALID_API_METHOD, "The $route endpoint only accepts " . implode(', ', $available_methods) . ", $method was used.", Response::HTTP_METHOD_NOT_ALLOWED); } - $api->throwError(Nameless2API::ERROR_INVALID_API_METHOD, 'If you are seeing this while in a browser, this means your API is functioning!', 404); + $api->throwError(Nameless2API::ERROR_INVALID_API_METHOD, 'If you are seeing this while in a browser, this means your API is functioning!', Response::HTTP_NOT_FOUND); } /** diff --git a/core/classes/Endpoints/KeyAuthEndpoint.php b/core/classes/Endpoints/KeyAuthEndpoint.php index 8ea22bcc9a..436b73bbfa 100644 --- a/core/classes/Endpoints/KeyAuthEndpoint.php +++ b/core/classes/Endpoints/KeyAuthEndpoint.php @@ -1,4 +1,5 @@ throwError(Nameless2API::ERROR_MISSING_API_KEY, 'Missing authorization header'); + $api->throwError(Nameless2API::ERROR_MISSING_API_KEY, 'Missing authorization header', Response::HTTP_UNAUTHORIZED); } $api_key = $api_key_header; } - return $this->validateKey($api, $api_key); + return $this->validateKey($api_key); } /** * Validate provided API key to make sure it matches. * - * @param Nameless2API $api Instance of API to use for database connection. * @param string $api_key API key to check. * @return bool Whether it matches or not. */ - private function validateKey(Nameless2API $api, string $api_key): bool { + private function validateKey(string $api_key): bool { $correct_key = Settings::get('mc_api_key'); if ($correct_key === null) { die('API key is null'); diff --git a/core/includes/image_upload.php b/core/includes/image_upload.php index 5351d29295..2fa6cb10f8 100644 --- a/core/includes/image_upload.php +++ b/core/includes/image_upload.php @@ -119,7 +119,7 @@ Redirect::to(URL::build('/profile/' . urlencode($user->data()->username))); } - http_response_code(500); + http_response_code(\Symfony\Component\HttpFoundation\Response::HTTP_BAD_REQUEST); $error = $image->getError() ?: 'Unknown error, check logs for more details'; ErrorHandler::logWarning('Image upload error: ' . $error); die($error); @@ -155,7 +155,7 @@ die('OK'); } catch (Exception $e) { - http_response_code(500); + http_response_code(\Symfony\Component\HttpFoundation\Response::HTTP_BAD_REQUEST); $error = $e->getMessage() ?: 'Unknown error, check logs for more details'; ErrorHandler::logWarning('Image upload exception: ' . $error); die($error); diff --git a/core/installation/includes/header.php b/core/installation/includes/header.php index 52e45a9597..5e9553cea3 100644 --- a/core/installation/includes/header.php +++ b/core/installation/includes/header.php @@ -2,7 +2,7 @@ $readme = file(ROOT_PATH . '/README.md'); $subheader = str_replace('#', '', $readme[0]); -if (isset($_SESSION['installer_language']) && is_file('custom/languages/' . $_SESSION['installer_language'] . '.json')) { +if (isset($_SESSION['installer_language']) && is_file('modules/Core/language/' . $_SESSION['installer_language'] . '.json')) { $installer_language = $_SESSION['installer_language']; } else { $installer_language = 'en_UK'; diff --git a/custom/panel_templates/Default/auth.tpl b/custom/panel_templates/Default/auth.tpl index 85726147cc..0b7180f856 100644 --- a/custom/panel_templates/Default/auth.tpl +++ b/custom/panel_templates/Default/auth.tpl @@ -21,6 +21,12 @@ + {if isset($TWO_FACTOR_AUTH)} +
+ +
+ {/if}
diff --git a/custom/panel_templates/Default/core/general_settings.tpl b/custom/panel_templates/Default/core/general_settings.tpl index 955a18392e..473b7d5c15 100644 --- a/custom/panel_templates/Default/core/general_settings.tpl +++ b/custom/panel_templates/Default/core/general_settings.tpl @@ -217,6 +217,17 @@
+
+ + +
diff --git a/custom/panel_templates/Default/forum/forums_settings.tpl b/custom/panel_templates/Default/forum/forums_settings.tpl index a7262cd3b4..cbb5b18269 100644 --- a/custom/panel_templates/Default/forum/forums_settings.tpl +++ b/custom/panel_templates/Default/forum/forums_settings.tpl @@ -67,6 +67,18 @@
+
+ + + + + +
+
diff --git a/dev/scripts/delete_empty_language_strings.php b/dev/scripts/delete_empty_language_strings.php index dcac194bd7..7c6d62dd27 100644 --- a/dev/scripts/delete_empty_language_strings.php +++ b/dev/scripts/delete_empty_language_strings.php @@ -5,7 +5,7 @@ } $language_files = glob('modules/*/language/*.json'); -$language_files = array_merge($language_files, glob('custom/languages/*.json')); +$language_files = array_merge($language_files, glob('modules/Core/language/*.json')); foreach ($language_files as $language_file) { $modified = false; diff --git a/dev/scripts/find_unused_language_terms.sh b/dev/scripts/find_unused_language_terms.sh index 3f87f71d7c..8810c135e7 100644 --- a/dev/scripts/find_unused_language_terms.sh +++ b/dev/scripts/find_unused_language_terms.sh @@ -7,7 +7,7 @@ fi UNUSED_TERMS_FOUND=false FILES=( - "custom/languages/en_UK.json" + "modules/Core/language/en_UK.json" "modules/Forum/language/en_UK.json" "modules/Cookie Consent/language/en_UK.json" "modules/Discord Integration/language/en_UK.json" diff --git a/install.php b/install.php index 468001f2b9..70ac94b748 100644 --- a/install.php +++ b/install.php @@ -37,7 +37,7 @@ // Select language if ( isset($_SESSION['installer_language']) - && is_file('custom/languages/' . $_SESSION['installer_language'] . '.json') + && is_file('modules/Core/language/' . $_SESSION['installer_language'] . '.json') ) { $language_short_code = $_SESSION['installer_language']; } else { @@ -56,8 +56,11 @@ } if (isset($_GET['language'])) { + if (str_contains($_GET['language'], '/')) { + die('Language code must not contain slash'); + } // Set language - if (is_file('custom/languages/' . $_GET['language'] . '.json')) { + if (is_file('modules/Core/language/' . $_GET['language'] . '.json')) { $_SESSION['installer_language'] = $_GET['language']; die('OK'); } diff --git a/modules/Cookie Consent/language/cs_CZ.json b/modules/Cookie Consent/language/cs_CZ.json index 79d945d913..2850aafd18 100644 --- a/modules/Cookie Consent/language/cs_CZ.json +++ b/modules/Cookie Consent/language/cs_CZ.json @@ -7,7 +7,7 @@ "cookie/cookie_popup_disallow": "Zakázat cookies", "cookie/cookie_popup_more_info": "Více informací", "cookie/cookies": "Cookies", - "cookie/update_settings": "Zobrazit cookies okno", + "cookie/update_settings": "Zobrazit nastavení cookies", "cookie/cookie_notice_error": "Zadejte prosím oznámení o cookies s maximálně 10 000 znaky.", "cookie/cookie_popup": "Tento web používá cookies pro vylepšení vašeho zážitku." } diff --git a/modules/Core/classes/Misc/Nameless2API.php b/modules/Core/classes/Misc/Nameless2API.php index f3dfb3b1fb..a83fc79ad2 100644 --- a/modules/Core/classes/Misc/Nameless2API.php +++ b/modules/Core/classes/Misc/Nameless2API.php @@ -1,4 +1,5 @@ throwError(self::ERROR_UNKNOWN_ERROR, $e->getMessage()); + $this->throwError(self::ERROR_UNKNOWN_ERROR, $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR); } } @@ -67,7 +67,7 @@ public function __construct(string $route, Language $api_language, Endpoints $en * @param int $status HTTP status code * @return never */ - public function throwError(string $error, $meta = null, int $status = 400): void { + public function throwError(string $error, $meta = null, int $status = Response::HTTP_BAD_REQUEST): void { $this->returnArray( array_merge(['error' => $error], $meta ? ['meta' => $meta] : []), $status @@ -112,7 +112,7 @@ public function getLanguage(): Language { * @param int $status HTTP status code * @return never */ - public function returnArray(array $array, int $status = 200): void { + public function returnArray(array $array, int $status = Response::HTTP_OK): void { http_response_code($status); die(self::encodeJson($array)); diff --git a/modules/Core/includes/endpoints/RegisterEndpoint.php b/modules/Core/includes/endpoints/RegisterEndpoint.php index 3f5a30698d..063b22ac9b 100644 --- a/modules/Core/includes/endpoints/RegisterEndpoint.php +++ b/modules/Core/includes/endpoints/RegisterEndpoint.php @@ -1,4 +1,5 @@ $user_id]; } catch (Exception $e) { - $api->throwError(CoreApiErrors::ERROR_UNABLE_TO_CREATE_ACCOUNT, $e->getMessage()); + $api->throwError(CoreApiErrors::ERROR_UNABLE_TO_CREATE_ACCOUNT, $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR); } } @@ -210,7 +211,7 @@ private function sendRegistrationEmail(Nameless2API $api, string $username, stri 'user_id' => $user_id ]); - $api->throwError(CoreApiErrors::ERROR_UNABLE_TO_SEND_REGISTRATION_EMAIL); + $api->throwError(CoreApiErrors::ERROR_UNABLE_TO_SEND_REGISTRATION_EMAIL, null, Response::HTTP_INTERNAL_SERVER_ERROR); } $api->returnArray(['message' => $api->getLanguage()->get('api', 'finish_registration_email')]); diff --git a/modules/Core/includes/endpoints/ServerInfoEndpoint.php b/modules/Core/includes/endpoints/ServerInfoEndpoint.php index 7785aeecf2..779e56c206 100644 --- a/modules/Core/includes/endpoints/ServerInfoEndpoint.php +++ b/modules/Core/includes/endpoints/ServerInfoEndpoint.php @@ -1,4 +1,5 @@ throwError(CoreApiErrors::ERROR_UNABLE_TO_UPDATE_SERVER_INFO, $e->getMessage(), 500); + $api->throwError(CoreApiErrors::ERROR_UNABLE_TO_UPDATE_SERVER_INFO, $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR); } $cache = new Cache(['name' => 'nameless', 'extension' => '.cache', 'path' => ROOT_PATH . '/cache/']); @@ -83,7 +84,7 @@ public function execute(Nameless2API $api): void { } } } catch (Exception $e) { - $api->throwError(CoreApiErrors::ERROR_UNABLE_TO_UPDATE_SERVER_INFO, $e->getMessage(), 500); + $api->throwError(CoreApiErrors::ERROR_UNABLE_TO_UPDATE_SERVER_INFO, $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR); } } @@ -105,7 +106,7 @@ public function execute(Nameless2API $api): void { ], intval($_POST['interval_seconds'] ?? 10) * 2); } } catch (Exception $e) { - $api->throwError(CoreApiErrors::ERROR_UNABLE_TO_UPDATE_SERVER_INFO, $e->getMessage(), 500); + $api->throwError(CoreApiErrors::ERROR_UNABLE_TO_UPDATE_SERVER_INFO, $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR); } $api->returnArray(array_merge(['message' => $api->getLanguage()->get('api', 'server_info_updated')])); diff --git a/modules/Core/includes/endpoints/UpdateUsernameEndpoint.php b/modules/Core/includes/endpoints/UpdateUsernameEndpoint.php index 97ddd925e7..474a9b662e 100644 --- a/modules/Core/includes/endpoints/UpdateUsernameEndpoint.php +++ b/modules/Core/includes/endpoints/UpdateUsernameEndpoint.php @@ -1,4 +1,5 @@ getDb()->update('users', $user->data()->id, $fields); } catch (Exception $e) { - $api->throwError(CoreApiErrors::ERROR_UNABLE_TO_UPDATE_USERNAME, null, 500); + $api->throwError(CoreApiErrors::ERROR_UNABLE_TO_UPDATE_USERNAME, null, Response::HTTP_INTERNAL_SERVER_ERROR); } $api->returnArray(['message' => $api->getLanguage()->get('api', 'username_updated')]); diff --git a/custom/languages/cs_CZ.json b/modules/Core/language/cs_CZ.json similarity index 96% rename from custom/languages/cs_CZ.json rename to modules/Core/language/cs_CZ.json index 17cba67005..90f3127785 100644 --- a/custom/languages/cs_CZ.json +++ b/modules/Core/language/cs_CZ.json @@ -16,14 +16,14 @@ "admin/announcement_order": "Pořadí", "admin/announcements": "Oznámení", "admin/api": "API", - "admin/api_endpoints": "API endpointy", - "admin/api_endpoints_info": "API endpointy umožňují doplňkům vytvářet cesty pro externí aplikace (jako je Minecraft a Discord) k interakci s vaším NamelessMC webem. {{docLinkStart}}Check out the API documentation here{{docLinkEnd}}", + "admin/api_endpoints": "Endpointy API", + "admin/api_endpoints_info": "Endpointy API umožňují doplňkům vytvářet cesty pro externí aplikace (jako je Minecraft a Discord) k interakci s vaším NamelessMC webem. {{docLinkStart}}Check out the API documentation here{{docLinkEnd}}", "admin/api_info": "API umožňuje pluginům a dalším službám interagovat s vaším webem, například {{pluginLinkStart}}oficiálnímu Nameless pluginu{{pluginLinkEnd}} a {{botLinkStart}}oficiálnímu NamelessMC Discord botovi{{botLinkEnd}}.", "admin/api_key": "Klíč API", "admin/api_key_regenerated": "Klíč API byl úspěšně znovu vygenerován.", "admin/api_registration_email": "Registrační e-mail API", "admin/api_settings_updated_successfully": "Nastavení API úspěšně aktualizována.", - "admin/api_url": "URL API", + "admin/api_url": "Adresa URL API", "admin/at_least_one_external": "Zadejte alespoň 1 externí skupinu (Minecraft nebo Discord)", "admin/authme_db_address": "Adresa AuthMe databáze", "admin/authme_db_name": "Název AuthMe databáze", @@ -59,8 +59,8 @@ "admin/cant_edit_this_group": "Nemůžete upravit oprávnění této skupiny!", "admin/cant_modify_root_user": "Nelze upravit hlavní skupinu tohoto uživatele!", "admin/cant_write_to_template": "Nepodařilo se upravit soubor šablony! Zkontrolujte jeho oprávnění.", - "admin/captcha_general": "Povolit Captchu na registrační stránce?", - "admin/captcha_login": "Povolit Captchu na přihlašovací stránce?", + "admin/captcha_general": "Zapnout Captchu na registrační stránce?", + "admin/captcha_login": "Zapnout Captchu na přihlašovací stránce?", "admin/captcha_secret_key": "Captcha tajný klíč", "admin/captcha_site_key": "Captcha klíč webu", "admin/captcha_type": "Typ Captcha", @@ -165,25 +165,25 @@ "admin/email_resend_failed": "Odeslání e-mailu se nezdařilo, zkontrolujte vaše nastavení e-mailů.", "admin/email_resent_successfully": "E-mail byl úspěšně znovu odeslán.", "admin/email_settings_updated_successfully": "Nastavení e-mailů byla úspěšně aktualizována.", - "admin/email_verification": "Povolit ověřování e-mailem?", + "admin/email_verification": "Zapnout ověřování e-mailem?", "admin/emails": "E-maily", "admin/emails_mass_message": "Hromadná e-mailová zpráva", "admin/emails_mass_message_loading": "Načítání... Nenačítejte stránku znovu. Může to chvíli trvat.", "admin/emails_mass_message_replacements": "Ve vaší zprávě můžete použít proměnné. Podporované proměnné: {username}, {sitename}", - "admin/enable": "Povolit", - "admin/enable_api": "Povolit API?", - "admin/enable_authme": "Povolit integraci AuthMe?", - "admin/enable_debug_mode": "Povolit režim ladění?", + "admin/enable": "Zapnout", + "admin/enable_api": "Zapnout API?", + "admin/enable_authme": "Zapnout integraci AuthMe?", + "admin/enable_debug_mode": "Zapnout režim ladění?", "admin/enable_mailer_help": "Pokud je povoleno, budou e-maily odesílány pomocí PHPMaileru místo výchozí služby systému. Může to pomoci s doručením, ale vyžaduje to nastavení poskytovatele SMTP. {{docLinkStart}}Zjistit více »{{docLinkEnd}}", - "admin/enable_maintenance_mode": "Povolit režim údržby?", - "admin/enable_minecraft_integration": "Povolit integraci Minecraftu?", - "admin/enable_nicknames_on_registration": "Povolit přezdívky při registraci uživatelů?", - "admin/enable_page_load_timer": "Povolit časovač načítání stránky?", - "admin/enable_placeholders": "Povolit placeholdery?", - "admin/enable_player_list": "Povolit seznam hráčů?", - "admin/enable_registration": "Povolit registrace?", - "admin/enable_status_query": "Povolit query stavu?", - "admin/enable_username_sync": "Povolit synchronizaci uživatelských jmen?", + "admin/enable_maintenance_mode": "Zapnout režim údržby?", + "admin/enable_minecraft_integration": "Zapnout integraci Minecraftu?", + "admin/enable_nicknames_on_registration": "Zapnout přezdívky při registraci uživatelů?", + "admin/enable_page_load_timer": "Zapnout časovač načítání stránky?", + "admin/enable_placeholders": "Zapnout placeholdery?", + "admin/enable_player_list": "Zapnout seznam hráčů?", + "admin/enable_registration": "Zapnout registrace?", + "admin/enable_status_query": "Zapnout zjišťování stavu?", + "admin/enable_username_sync": "Zapnout synchronizaci uživatelských jmen?", "admin/enable_username_sync_info": "Pokud povolíte tuto možnost, uživatelská jména na webu budou aktualizována tak, aby odpovídala uživatelským jménům ve hře. Toto se bude dít, když herní plugin odešle seznam UUID a uživatelských jmen online hráčů na web.", "admin/enabled": "Povoleno", "admin/enter_authme_db_details": "Zadejte platné podrobnosti databáze.", @@ -192,7 +192,7 @@ "admin/existing_rules": "Existující pravidla", "admin/external_query": "Použít externí query?", "admin/face": "Obličej", - "admin/facebook_url": "URL Facebooku", + "admin/facebook_url": "Adresa URL Facebooku", "admin/fatal_log": "Fatální protokol", "admin/favicon_image_x": "Favikona: {{imageName}}", "admin/favicon_reset_successfully": "Favikona úspěšně obnovena.", @@ -227,7 +227,7 @@ "admin/group_order": "Pořadí skupiny", "admin/group_staff": "Je skupina určena pro tým?", "admin/group_sync": "Synchronizace skupin", - "admin/group_sync_info": "Můžete nastavit API, aby automaticky měnilo skupinu uživatele na webu při změně jeho skupiny ve hře. Stačí níže zadat název / ID skupiny ve hře a skupinu, se kterou má být herní skupina synchronizována.", + "admin/group_sync_info": "Zde lze nastavit, aby API automaticky měnilo skupinu uživatele na webu při změně jeho skupiny ve hře. Stačí níže zadat název / ID skupiny ve hře a skupinu, se kterou má být herní skupina synchronizována.", "admin/group_sync_logs": "Změny synchronizace skupin", "admin/group_sync_plugin_not_set_up": "Herní plugin není nastaven nebo nebyl vybrán žádný server pro synchronizaci", "admin/group_sync_rule_created_successfully": "Synchronizační pravidlo bylo úspěšně vytvořeno.", @@ -250,7 +250,7 @@ "admin/hook_name": "Název webhooku", "admin/hook_select_info": "Jsou zobrazeny pouze webhooky s vybranou událostí 'Nové téma' nebo 'Odpověď na téma'.", "admin/hook_type": "Typ webhooku", - "admin/hook_url": "URL webhooku", + "admin/hook_url": "Adresa URL webhooku", "admin/hooks": "Webhooky", "admin/hooks_info": "Webhooky umožňují posílat oznámení externím službám, když nastanou určité události.", "admin/host": "Hostitel", @@ -271,7 +271,7 @@ "admin/invalid_file_type": "Neplatný typ souboru!", "admin/invalid_hook_events": "Musíte vybrat alespoň 1 událost", "admin/invalid_hook_name": "Neplatný název webhooku", - "admin/invalid_hook_url": "Neplatná URL webhooku", + "admin/invalid_hook_url": "Neplatná adresa URL webhooku", "admin/ip_address": "IP adresa", "admin/keywords": "Klíčová slova", "admin/layout": "Rozložení", @@ -508,7 +508,7 @@ "admin/source": "Zdroj", "admin/statistics": "Statistiky", "admin/stats": "Statistiky", - "admin/status_page": "Povolit stavovou stránku?", + "admin/status_page": "Zapnout stavovou stránku?", "admin/status_query_help": "Pokud povolíte tuto možnost, bude na stavové stránce zobrazen stav serveru (online nebo offline).", "admin/styles": "Styly", "admin/successfully_updated": "Úspěšně aktualizováno", @@ -537,7 +537,7 @@ "admin/topics": "Témata", "admin/total_users": "Celkový počet uživatelů", "admin/twitter_dark_theme": "Použít tmavé téma Twitteru?", - "admin/twitter_url": "URL Twitteru", + "admin/twitter_url": "Adresa URL Twitteru", "admin/type": "Typ", "admin/type_required": "Je vyžadován typ", "admin/unable_to_delete_group": "Nelze odstranit výchozí skupinu, nebo skupinu, která může zobrazit panel. Nejprve prosím aktualizujte nastavení skupiny!", @@ -562,7 +562,7 @@ "admin/updated_x": "Aktualizováno: {{updatedAt}}", "admin/upload_new_image": "Nahrát nový obrázek", "admin/use_friendly_urls": "Přátelské adresy", - "admin/use_friendly_urls_help": "Pokud je tato možnost povolena, budou použity lépe vypadající webové adresy. Pro funkčnost této možnosti musíte povolit použití souborů mod_rewrite a .htaccess. {{docLinkStart}}Zjistit více »{{docLinkEnd}}", + "admin/use_friendly_urls_help": "Při povolení této možnosti budou použity lépe vypadající webové adresy. Pro správnou funkčnost této možnosti musíte povolit použití souborů mod_rewrite a .htaccess. {{docLinkStart}}Zjistit více »{{docLinkEnd}}", "admin/user": "Uživatel", "admin/user_deleted": "Uživatel úspěšně odstraněn.", "admin/user_id": "ID uživatele", @@ -593,7 +593,7 @@ "admin/widget_updated": "Widget aktualizován.", "admin/widgets": "Widgety", "admin/x_directory_not_writable": "Adresář {{directory}} není zapisovatelný!", - "admin/youtube_url": "URL YouTube", + "admin/youtube_url": "Adresa URL YouTube", "api/account_validated": "Účet úspěšně ověřen", "api/finish_registration_email": "Podívejte se do vaší e-mailové schránky pro dokončení registrace.", "api/finish_registration_link": "Klikněte na následující odkaz pro dokončení registrace:", @@ -707,7 +707,7 @@ "general/total_posts": "Celkem příspěvků", "general/total_threads": "Celkem vláken", "general/unlink": "Odpojit", - "general/url": "URL", + "general/url": "Adresa URL", "general/users_registered": "Zaregistrovaní uživatelé", "general/version": "Verze: {{version}}", "general/view": "Zobrazit", @@ -742,7 +742,7 @@ "installer/finish": "Dokončit", "installer/finish_message": "Děkujeme za instalaci NamelessMC! Nyní můžete pokračovat do panelu, kde můžete dále nastavit váš web.", "installer/friendly_urls": "Přátelské adresy", - "installer/friendly_urls_info": "Přátelské adresy zlepšují čitelnost adres URL ve vašem prohlížeči.
Například zpriklad.cz/index.php?route=/forum by se stalo
priklad.cz/forum
Důležité!
Váš server musí být pro správnou funkčnost této možnosti správně nakonfigurován. Zda můžete tuto možnost povolit zjistíte kliknutím sem.
", + "installer/friendly_urls_info": "Přátelské adresy zlepšují čitelnost adres URL ve vašem prohlížeči.
Například z adresy priklad.cz/index.php?route=/forum by se stala
priklad.cz/forum
Důležité!
Váš server musí být pro správnou funkčnost této možnosti správně nakonfigurován. Zda můžete tuto možnost zapnout zjistíte kliknutím sem.
", "installer/general_configuration": "Základní konfigurace", "installer/host": "Adresa", "installer/host_help": "Adresa je základní URL vašeho webu. Nepatří sem podsložky z pole Instalační cesta ani http(s)://!", @@ -916,7 +916,7 @@ "user/email_changed_successfully": "E-mailová adresa úspěšně změněna.", "user/email_or_username": "E-mail nebo uživatelské jméno", "user/email_required": "Je vyžadována e-mailová adresa.", - "user/enable": "Povolit", + "user/enable": "Zapnout", "user/enabled": "Povoleno", "user/enter_new_password": "Potvrďte vaší e-mailovou adresu a zadejte níže nové heslo.", "user/feed": "Kanál", @@ -1053,7 +1053,7 @@ "admin/debug_link_toast": "{{linkStart}}Klikněte sem{{linkEnd}} pro zobrazení ladicího odkazu.", "admin/editing_integration_for_x": "Úprava integrace {{integration}} u uživatele {{user}}", "admin/editing_integration_x": "Úprava integrace {{integration}}", - "admin/email_language_info": "Nevidíte váš jazyk? Ujistěte se, že je jeho jazykový soubor v adresáři /custom/languages/ zapisovatelný vaším webovým serverem.", + "admin/email_language_info": "Nevidíte váš jazyk? Ujistěte se, že je jeho jazykový soubor v adresáři /modules/Core/language/ zapisovatelný vaším webovým serverem.", "admin/email_port": "Port", "admin/group_cloned_successfully": "Skupina úspěšně naklonována.", "admin/identifier": "Identifikátor", @@ -1180,7 +1180,7 @@ "admin/invalid_recaptcha_settings_info": "Zvažte vyzkoušení přihlášení/registrace v anonynmním okně pro ujištění se, že vaše Captcha funguje!", "admin/group_sync_server": "Vyberte Minecraft server, který bude použit při synchronizaci skupin", "admin/no_group_sync_server": "Žádný synchronizační server", - "admin/redirect_url": "URL přesměrování", + "admin/redirect_url": "Přesměrování adresy URL", "general/log_out_click": "Klikněte sem pro odhlášení", "general/log_out_complete": "Odhlášení bylo úspěšné. Klikněte {{linkStart}}sem{{linkEnd}} pro pokračování.", "general/rate_limit": "Zkuste to prosím znovu za {{expires}} sekund", @@ -1242,7 +1242,7 @@ "admin/clone_group": "Klonovat skupinu", "admin/user_banned_webhook": "Uživatel {{punished}} byl zabanován z webu uživatelem {{punisher}}.", "admin/emoji_style": "Styl emotikonů", - "admin/emoji_style_help": "Změnit používaný styl emotikonu:
• Nativní {{nativeExample}}
• Twemoji {{twemojiExample}}
• JoyPixels {{joypixelsExample}}", + "admin/emoji_style_help": "Změnit používaný styl emotikonů:
• Nativní {{nativeExample}}
• Twemoji {{twemojiExample}}
• JoyPixels {{joypixelsExample}}", "admin/emoji_native": "Nativní", "admin/emoji_twemoji": "Twemoji", "admin/emoji_joypixels": "JoyPixels", @@ -1258,7 +1258,7 @@ "installer/module_core_description": "Tento doplněk je vyžadován pro správnou funkčnost NamelessMC.", "installer/module_discord-integration_description": "Umožňuje uživatelům propojit si svůj Discord účet s jejich účtem na webu a provádět různé synchronizační akce.", "admin/auto_language_help": "Pokud je tato možnost povolena, mohou hosté a odhlášení uživatelé nechat web automaticky rozpoznat jejich preferovaný jazyk.", - "admin/enable_auto_language": "Povolit automatickou detekci jazyka?", + "admin/enable_auto_language": "Zapnout automatickou detekci jazyka?", "admin/og_image_reset_successfully": "Původní obrázek úspěšně resetován.", "admin/og_image_updated_successfully": "Původní obrázek úspěšně upraven.", "admin/fallback_og_image_x": "Náhradní původní obrázek: {{imageName}}", @@ -1332,5 +1332,9 @@ "user/minecraft_account": "Účet Minecraft", "user/reaction_score": "Reakční skóre", "user/received": "Obdrženo", - "api/groups_updates_ignored": "Požadavek na synchronizaci skupiny je ignorován, protože integrace Minecraftu je zakázána nebo server není nakonfigurován jako server pro synchronizaci skupiny v panelu." + "api/groups_updates_ignored": "Požadavek na synchronizaci skupiny je ignorován, protože integrace Minecraftu je zakázána nebo server není nakonfigurován jako server pro synchronizaci skupiny v panelu.", + "admin/default_description": "Výchozí popis", + "admin/default_keywords": "Výchozí klíčová slova", + "admin/require_two_factor_for_staffcp": "Vyžadovat dvoufaktorové ověření pro přihlášení do panelu (pokud jej má uživatel povolené)", + "user/two_factor_auth_code": "Kód dvoufaktorového ověření" } diff --git a/custom/languages/da_DK.json b/modules/Core/language/da_DK.json similarity index 99% rename from custom/languages/da_DK.json rename to modules/Core/language/da_DK.json index f2134039d7..6313f72a73 100644 --- a/custom/languages/da_DK.json +++ b/modules/Core/language/da_DK.json @@ -652,7 +652,7 @@ "admin/confirm_delete_page": "Er du sikker på, at du vil slette denne side?", "admin/confirm_group_deletion": "Er du sikker på, at du vil slette denne gruppe {{group}}?", "admin/creating_announcement": "Oprettelse af meddelelse", - "admin/email_language_info": "Kan du ikke se dit sprog? Sørg for, at dens sprogfil er skrivbar af din hjemmeside i /custom/languages/.", + "admin/email_language_info": "Kan du ikke se dit sprog? Sørg for, at dens sprogfil er skrivbar af din hjemmeside i /modules/Core/language/.", "admin/email_port_invalid": "Indsæt venligst en gyldig e-mail port.", "admin/emails_mass_message_loading": "Indlæser... Lad være med at genindlæse siden. Dette kan tage et stykke tid.", "admin/enable_minecraft_integration": "Vil du aktivere Minecraft-integration?", diff --git a/custom/languages/de_DE.json b/modules/Core/language/de_DE.json similarity index 99% rename from custom/languages/de_DE.json rename to modules/Core/language/de_DE.json index fa09b97a85..0e39ab02d9 100644 --- a/custom/languages/de_DE.json +++ b/modules/Core/language/de_DE.json @@ -1072,7 +1072,7 @@ "admin/authme_db_password_hidden": "Das Passwort der AuthMe-Datenbank ist aus Sicherheitsgründen verborgen.", "admin/bedrock_help": "Wähle diese Option, wenn der Server ein Bedrock-Server ist.", "admin/can_unlink_integration": "Können Benutzer die Integration aufheben?", - "admin/email_language_info": "Du siehst deine Sprache nicht? Vergewisser dich, dass die Sprachdatei in /custom/languages/ für deinen Webserver schreibbar ist.", + "admin/email_language_info": "Du siehst deine Sprache nicht? Vergewisser dich, dass die Sprachdatei in /modules/Core/language/ für deinen Webserver schreibbar ist.", "admin/enable_placeholders": "Platzhalter aktivieren?", "admin/group_order": "Gruppen Sortiertung", "admin/integration": "Integration", @@ -1262,7 +1262,7 @@ "admin/enable_auto_language": "Automatische Spracherkennung aktivieren?", "admin/og_image_reset_successfully": "OG-Image erfolgreich zurückgesetzt.", "admin/og_image_updated_successfully": "OG-Image erfolgreich aktualisiert.", - "admin/fallback_og_image_x": "Fallback OG image: {{imageName}}", + "admin/fallback_og_image_x": "Fallback OG Image: {{imageName}}", "admin/image": "Image", "admin/reset_og_image": "OG-Image zurücksetzen", "general/sql_query": "Query", @@ -1327,10 +1327,14 @@ "admin/site_widgets": "Website-Widgets", "general/on": "an", "user/given": "Gegeben", - "user/minecraft_account": "Minecraft Account", + "user/minecraft_account": "Minecraft Konto", "user/profile_posts_score": "Bewertung der Profilbeiträge", "user/reaction_score": "Bewertung der Reaktion", "user/received": "Empfangen", "user/integration_linked": "Du hast dein {{integration}}-Konto erfolgreich verknüpft.", - "api/groups_updates_ignored": "Gruppen-Sync-Anfrage wird ignoriert, weil die Minecraft-Integration deaktiviert ist oder der Server nicht als Gruppen-Sync-Server im StaffCP konfiguriert ist." + "api/groups_updates_ignored": "Gruppen-Sync-Anfrage wird ignoriert, weil die Minecraft-Integration deaktiviert ist oder der Server nicht als Gruppen-Sync-Server im StaffCP konfiguriert ist.", + "admin/default_description": "Standard Beschreibung", + "admin/default_keywords": "Standard-Schlüsselwörter", + "admin/require_two_factor_for_staffcp": "Erforderst du eine Zwei-Faktor-Authentifizierung für die StaffCP-Anmeldung? (falls für den Benutzer aktiviert)", + "user/two_factor_auth_code": "Zwei-Faktor-Authentifizierungscode" } diff --git a/custom/languages/el_GR.json b/modules/Core/language/el_GR.json similarity index 100% rename from custom/languages/el_GR.json rename to modules/Core/language/el_GR.json diff --git a/custom/languages/en_UK.json b/modules/Core/language/en_UK.json similarity index 99% rename from custom/languages/en_UK.json rename to modules/Core/language/en_UK.json index bf015d2750..fa089a2b20 100644 --- a/custom/languages/en_UK.json +++ b/modules/Core/language/en_UK.json @@ -576,6 +576,7 @@ "admin/render_profile_post_hook_info": "Render profile post", "admin/report_hook_info": "Report creation", "admin/require_integration": "Require users to link and verify integration", + "admin/require_two_factor_for_staffcp": "Require two factor authentication for StaffCP login (if enabled for the user)", "admin/required": "Required", "admin/resend_activation_email": "Resend Activation Email", "admin/reset_background": "Reset Background", @@ -1287,6 +1288,7 @@ "user/to": "To", "user/topic_updates": "Get emails for topics you follow", "user/two_factor_auth": "Two Factor Authentication", + "user/two_factor_auth_code": "Two Factor Authentication Code", "user/unable_to_connect_to_authme_db": "Unable to connect to the AuthMe database. If this error persists, please contact an administrator.", "user/unable_to_send_forgot_password_email": "Unable to send forgot password email. Please contact an administrator.", "user/unblock_user": "Unblock User", diff --git a/custom/languages/en_US.json b/modules/Core/language/en_US.json similarity index 99% rename from custom/languages/en_US.json rename to modules/Core/language/en_US.json index f4d644e578..b30a7f5397 100644 --- a/custom/languages/en_US.json +++ b/modules/Core/language/en_US.json @@ -1080,7 +1080,7 @@ "admin/can_unlink": "Can Unlink", "admin/can_unlink_integration": "Can users unlink integration?", "admin/editing_integration_x": "Editing integration {{integration}}", - "admin/email_language_info": "Not seeing your language? Make sure its language file is writable by your webserver in /custom/languages/.", + "admin/email_language_info": "Not seeing your language? Make sure its language file is writable by your webserver in /modules/Core/language/.", "admin/group_cloned_successfully": "Group cloned successfully.", "admin/integration": "Integration", "admin/integration_identifier": "{{integration}} Identifier", diff --git a/custom/languages/es_419.json b/modules/Core/language/es_419.json similarity index 100% rename from custom/languages/es_419.json rename to modules/Core/language/es_419.json diff --git a/custom/languages/es_ES.json b/modules/Core/language/es_ES.json similarity index 98% rename from custom/languages/es_ES.json rename to modules/Core/language/es_ES.json index e224e2ad55..5d2ceb1f50 100644 --- a/custom/languages/es_ES.json +++ b/modules/Core/language/es_ES.json @@ -1058,7 +1058,7 @@ "admin/announcement_hook_info": "Creación de anuncios", "admin/can_unlink": "Puede desvincularse", "admin/can_unlink_integration": "¿Pueden los usuarios desvincularse de la integración?", - "admin/email_language_info": "¿No ve su idioma? Asegúrese de que su archivo de idioma es escribible por su servidor web en /custom/languages/.", + "admin/email_language_info": "¿No ve su idioma? Asegúrese de que su archivo de idioma es escribible por su servidor web en /modules/Core/language/.", "admin/identifier": "Identificador", "admin/integration_identifier_invalid": "El identificador {{integration}} no es válido.", "admin/integration_identifier_required": "Se requiere el identificador {{integration}}.", @@ -1319,5 +1319,22 @@ "admin/queue_task_output": "Resultado de la tarea", "admin/queue_task_scheduled_at": "Programado para", "admin/queue_task_scheduled_for": "Programado para", - "admin/queue_task_status": "Estado" + "admin/queue_task_status": "Estado", + "user/integration_linked": "Has vinculado con éxito tu cuenta de {{integration}}.", + "admin/default_description": "Descripción Predeterminada", + "admin/default_keywords": "Palabras Clave Predeterminadas", + "admin/profile_widgets": "Widgets de Perfil", + "admin/reaction_added_event_info": "Reacción añadida", + "admin/reaction_deleted_event_info": "Reacción eliminada", + "admin/site_widgets": "Widgets del Sitio", + "api/groups_updates_ignored": "La solicitud de sincronización de grupos fue ignorada, porque la integración con Minecraft está desactivada o el servidor no está configurado como el servidor de sincronización de grupos en StaffCP.", + "admin/require_two_factor_for_staffcp": "Requerir autenticación de dos factores para el inicio de sesión en StaffCP (si está habilitada para el usuario)", + "user/profile_posts_score": "Puntuación de publicaciones de perfil", + "user/reaction_score": "Puntuación de reacciones", + "user/received": "Recibido", + "user/given": "Visto", + "user/minecraft_account": "Cuenta de Minecraft", + "user/two_factor_auth_code": "Código de Autenticación de Dos Factores", + "general/on": "Encendido", + "admin/custom_score": "Puntuación Personalizada" } diff --git a/custom/languages/fi_FI.json b/modules/Core/language/fi_FI.json similarity index 100% rename from custom/languages/fi_FI.json rename to modules/Core/language/fi_FI.json diff --git a/custom/languages/fr_FR.json b/modules/Core/language/fr_FR.json similarity index 99% rename from custom/languages/fr_FR.json rename to modules/Core/language/fr_FR.json index 5de1c54cee..d34f44e243 100644 --- a/custom/languages/fr_FR.json +++ b/modules/Core/language/fr_FR.json @@ -957,7 +957,7 @@ "admin/editing_integration_x": "Modification de l’intégration {{integration}}}", "admin/editing_language": "Édition du langage", "admin/editing_messages": "Édition du Message", - "admin/email_language_info": "Tu ne vois pas ton langage? Assurez-vous que son fichier de langue est en écriture par votre serveur web dans /custom/languages/ .", + "admin/email_language_info": "Tu ne vois pas ton langage? Assurez-vous que son fichier de langue est en écriture par votre serveur web dans /modules/Core/language/ .", "admin/email_logs": "Masse Emails", "admin/email_message_greeting": "Salutation", "admin/email_message_message": "Message", diff --git a/custom/languages/hr_HR.json b/modules/Core/language/hr_HR.json similarity index 100% rename from custom/languages/hr_HR.json rename to modules/Core/language/hr_HR.json diff --git a/custom/languages/hu_HU.json b/modules/Core/language/hu_HU.json similarity index 99% rename from custom/languages/hu_HU.json rename to modules/Core/language/hu_HU.json index ef75933eef..da25361d8d 100644 --- a/custom/languages/hu_HU.json +++ b/modules/Core/language/hu_HU.json @@ -310,7 +310,7 @@ "admin/editing_profile_field": "Profil mező szerkesztése", "admin/editing_widget_x": "{{widget}} Widget szerkesztése", "admin/email_errors_purged_successfully": "E-mail hibák sikeresen törölve.", - "admin/email_language_info": "Nem látod a nyelved? Győződj meg arról, hogy a nyelvi fájl a webszerver által írható a /custom/languages/ mappában.", + "admin/email_language_info": "Nem látod a nyelved? Győződj meg arról, hogy a nyelvi fájl a webszerver által írható a /modules/Core/language/ mappában.", "admin/email_resent_successfully": "E-mail újraküldés sikeres.", "admin/enable_api": "API Engedélyezése?", "user/avatar_set_successfully": "Avatár beállítása sikeres.", diff --git a/custom/languages/id_ID.json b/modules/Core/language/id_ID.json similarity index 100% rename from custom/languages/id_ID.json rename to modules/Core/language/id_ID.json diff --git a/custom/languages/it_IT.json b/modules/Core/language/it_IT.json similarity index 99% rename from custom/languages/it_IT.json rename to modules/Core/language/it_IT.json index d33e9da089..299a8b7f0d 100644 --- a/custom/languages/it_IT.json +++ b/modules/Core/language/it_IT.json @@ -982,7 +982,7 @@ "admin/bedrock": "Bedrock?", "user/group_has_been_added": "Il gruppo {{group}} è stato aggiunto all’utente {{user}}", "user/group_has_been_removed": "Il gruppo {{group}} è stato rimosso dall’utente {{user}}", - "admin/email_language_info": "Non vedi la tua lingua? Assicurati che il file sia scrivibile dal tuo webserver in /custom/languages/.", + "admin/email_language_info": "Non vedi la tua lingua? Assicurati che il file sia scrivibile dal tuo webserver in /modules/Core/language/.", "user/no_providers": "Nessun provider di autenticazione è stato configurato.", "general/normal": "Normale", "general/orange": "Arancio", diff --git a/custom/languages/ja_JP.json b/modules/Core/language/ja_JP.json similarity index 99% rename from custom/languages/ja_JP.json rename to modules/Core/language/ja_JP.json index efa95c5d46..d2cc94e12f 100644 --- a/custom/languages/ja_JP.json +++ b/modules/Core/language/ja_JP.json @@ -1076,7 +1076,7 @@ "admin/can_unlink": "リンク解除可能", "admin/editing_integration_for_x": "{{user}}の{{integration}}連携を編集", "admin/linking_integration_for_x": "{{user}}の{{integration}} 連携をリンク", - "admin/email_language_info": "あなたの言語が表示されませんか?ウェブサーバーの/custom/languages/にある言語ファイルが書き込み可能であることを確認してください。", + "admin/email_language_info": "あなたの言語が表示されませんか?ウェブサーバーの/modules/Core/language/にある言語ファイルが書き込み可能であることを確認してください。", "admin/page_url_contains_nameless_path": "カスタムページがNamelessMCのページを上書きしてしまいます。", "admin/placeholders_last_updated_time": "最終更新: {{time}}", "admin/require_integration": "ユーザーにリンクと連携の検証を要求する", diff --git a/custom/languages/ko_KR.json b/modules/Core/language/ko_KR.json similarity index 100% rename from custom/languages/ko_KR.json rename to modules/Core/language/ko_KR.json diff --git a/custom/languages/lt_LT.json b/modules/Core/language/lt_LT.json similarity index 100% rename from custom/languages/lt_LT.json rename to modules/Core/language/lt_LT.json diff --git a/custom/languages/lv_LV.json b/modules/Core/language/lv_LV.json similarity index 100% rename from custom/languages/lv_LV.json rename to modules/Core/language/lv_LV.json diff --git a/custom/languages/nl_NL.json b/modules/Core/language/nl_NL.json similarity index 99% rename from custom/languages/nl_NL.json rename to modules/Core/language/nl_NL.json index c154b79215..c3d717953d 100644 --- a/custom/languages/nl_NL.json +++ b/modules/Core/language/nl_NL.json @@ -1038,7 +1038,7 @@ "admin/api_endpoints_info": "API eindpunten staan Modules toe dat externe applicaties (zoals Minecraft en Discord) te kunnen communiceren met je NamelessMC website. {{docLinkStart}}Bekijk de API documentatie hier{{docLinkEnd}}", "admin/debug_link": "Debug link", "admin/debug_link_toast": "{{linkStart}}Klik hier{{linkEnd}} om de debuglink te bekijken.", - "admin/email_language_info": "Zie je je taal niet? Zorg ervoor dat de taalbestanden schrijfbaar zijn door je webserver in /custom/languages/.", + "admin/email_language_info": "Zie je je taal niet? Zorg ervoor dat de taalbestanden schrijfbaar zijn door je webserver in /modules/Core/language/.", "admin/at_least_one_external": "Vul alstublieft minstens 1 externe groep in (Minecraft of Discord)", "admin/ban_hook_info": "Gebruiker verbannen", "admin/bedrock": "Bedrock?", diff --git a/custom/languages/no_NO.json b/modules/Core/language/no_NO.json similarity index 99% rename from custom/languages/no_NO.json rename to modules/Core/language/no_NO.json index ce40de78d3..a86ace9808 100644 --- a/custom/languages/no_NO.json +++ b/modules/Core/language/no_NO.json @@ -1008,7 +1008,7 @@ "admin/ban_hook_info": "Bruker utestengt", "admin/custom_content": "Egendefinert innhold", "admin/editing_integration_for_x": "Redigerer {{integration}}-integreringen for {{user}}", - "admin/email_language_info": "Ser du ikke språket ditt? Sjekk om språkfilen er skrivbar av webserveren i /custom/languages/.", + "admin/email_language_info": "Ser du ikke språket ditt? Sjekk om språkfilen er skrivbar av webserveren i /modules/Core/language/.", "admin/bedrock_help": "Velg dette alternativet hvis serveren er en Bedrock-server.", "admin/captcha_general": "Aktiver Captcha på registreringssiden?", "admin/captcha_login": "Aktiver Captcha på påloggingssiden?", diff --git a/custom/languages/pl_PL.json b/modules/Core/language/pl_PL.json similarity index 99% rename from custom/languages/pl_PL.json rename to modules/Core/language/pl_PL.json index cd09498677..1a3b83c9eb 100644 --- a/custom/languages/pl_PL.json +++ b/modules/Core/language/pl_PL.json @@ -1023,7 +1023,7 @@ "user/x_replies": "{{count}} komentarzy", "user/you_have_been_banned": "Zostałeś zbanowany!", "user/you_have_received_a_warning": "Dostałeś ostrzeżenie!", - "admin/email_language_info": "Nie widzisz swojego języka? Upewnij się, że plik językowy jest zapisywany przez serwer WWW w katalogu /custom/languages/.", + "admin/email_language_info": "Nie widzisz swojego języka? Upewnij się, że plik językowy jest zapisywany przez serwer WWW w katalogu /modules/Core/language/.", "admin/administrator": "Administrator", "admin/at_least_one_external": "Podaj co najmniej 1 grupę zewnętrzną (Minecraft lub Discord)", "admin/authme_db_password_hidden": "Hasło do bazy danych AuthMe jest ukryte ze względów bezpieczeństwa.", diff --git a/custom/languages/pt_BR.json b/modules/Core/language/pt_BR.json similarity index 99% rename from custom/languages/pt_BR.json rename to modules/Core/language/pt_BR.json index 4a7001e23b..1995096d38 100644 --- a/custom/languages/pt_BR.json +++ b/modules/Core/language/pt_BR.json @@ -1048,7 +1048,7 @@ "user/x_replies": "{{count}} respostas", "user/you_have_been_banned": "Você foi banido!", "user/you_have_received_a_warning": "Você recebeu uma advertencia!", - "admin/email_language_info": "Não está vendo seu idioma? Certifique-se de que seu arquivo de idioma seja gravável pelo seu servidor web em /custom/languages/.", + "admin/email_language_info": "Não está vendo seu idioma? Certifique-se de que seu arquivo de idioma seja gravável pelo seu servidor web em /modules/Core/language/.", "admin/can_unlink": "Pode desvincular", "admin/at_least_one_external": "Insira pelo menos 1 grupo externo (Minecraft ou Discord)", "admin/ban_hook_info": "Usuário banido", diff --git a/custom/languages/ro_RO.json b/modules/Core/language/ro_RO.json similarity index 99% rename from custom/languages/ro_RO.json rename to modules/Core/language/ro_RO.json index 368afcd668..d81b71eadf 100644 --- a/custom/languages/ro_RO.json +++ b/modules/Core/language/ro_RO.json @@ -925,7 +925,7 @@ "admin/api_endpoints_info": "API Endpoint-urile permit modulelor să creeze metode pentru aplicațiile externe (precum Minecraft și Discord) să interacționeze cu website-ul tau. Verifică documentația pentru API {{docLinkStart}}aici{{docLinkEnd}}", "admin/clear_cache": "Curata Cache-ul template-urilor", "admin/editing_integration_for_x": "Editand integrarea {{integration}} pentru {{user}}", - "admin/email_language_info": "Nu vezi limba ta? Asigura-te ca fila de limba are permisiuni de scriere de catre webserver-ul tau in /custom/languages.", + "admin/email_language_info": "Nu vezi limba ta? Asigura-te ca fila de limba are permisiuni de scriere de catre webserver-ul tau in /modules/Core/language.", "admin/use_external_mail_server": "Foloseste server de mail extern", "admin/force_tfa_warning": "Asigura-te ca stii ce face asta sau risti sa te blochezi pe tine si pe restul membrilor din grup pe dinafara.", "admin/debug_link_toast": "Link-ul de depanare a fost copiat!
Vizualizeaza logul {{linkStart}}aici{{linkEnd}}", diff --git a/custom/languages/ru_RU.json b/modules/Core/language/ru_RU.json similarity index 99% rename from custom/languages/ru_RU.json rename to modules/Core/language/ru_RU.json index f17729d421..2a7831c12a 100644 --- a/custom/languages/ru_RU.json +++ b/modules/Core/language/ru_RU.json @@ -1080,7 +1080,7 @@ "general/and_x_more": "и {{count}}", "general/internet_explorer_header": "Internet Explorer", "general/internet_explorer_info": "Internet Explorer iне поддерживается. Перейдите на более современный браузер.", - "admin/email_language_info": "Отсутствует ваш язык? Убедитесь, что файл с переводом доступен для записи в /custom/languages.", + "admin/email_language_info": "Отсутствует ваш язык? Убедитесь, что файл с переводом доступен для записи в /modules/Core/language.", "admin/facebook_url": "Facebook URL", "admin/integration": "Интеграция", "admin/integration_sync_not_supported": "Синхронизация недоступна для данного сервиса!", diff --git a/custom/languages/sk_SK.json b/modules/Core/language/sk_SK.json similarity index 99% rename from custom/languages/sk_SK.json rename to modules/Core/language/sk_SK.json index 4ce1f09d11..4cb5c501b7 100644 --- a/custom/languages/sk_SK.json +++ b/modules/Core/language/sk_SK.json @@ -1071,7 +1071,7 @@ "admin/can_unlink": "Dá sa odpojiť", "admin/can_unlink_integration": "Môžu používatelia odpojiť integráciu?", "admin/cloning_group": "Klonovanie skupiny {{group}}", - "admin/email_language_info": "Nevidíte svoj jazyk? Uistite sa, že do jeho jazykového súboru môže váš webový server zapisovať v /custom/languages/.", + "admin/email_language_info": "Nevidíte svoj jazyk? Uistite sa, že do jeho jazykového súboru môže váš webový server zapisovať v /modules/Core/language/.", "admin/group_cloned_successfully": "Skupina bola úspešne naklonovaná.", "admin/host": "Host", "admin/integration": "Integrácia", @@ -1331,5 +1331,8 @@ "admin/reaction_deleted_event_info": "Reakcia odstránená", "admin/site_widgets": "Widgety webu", "admin/custom_score": "Vlastné skóre", - "user/given": "Dané" + "user/given": "Dané", + "api/groups_updates_ignored": "Požiadavka na synchronizáciu skupiny je ignorovaná, pretože integrácia Minecraftu je vypnutá alebo server nie je nakonfigurovaný ako server na synchronizáciu skupiny v systéme StaffCP.", + "admin/default_description": "Predvolený opis", + "admin/default_keywords": "Predvolené kľúčové slová" } diff --git a/custom/languages/sl_SI.json b/modules/Core/language/sl_SI.json similarity index 100% rename from custom/languages/sl_SI.json rename to modules/Core/language/sl_SI.json diff --git a/custom/languages/sq_AL.json b/modules/Core/language/sq_AL.json similarity index 100% rename from custom/languages/sq_AL.json rename to modules/Core/language/sq_AL.json diff --git a/custom/languages/sv_SE.json b/modules/Core/language/sv_SE.json similarity index 99% rename from custom/languages/sv_SE.json rename to modules/Core/language/sv_SE.json index 09d1affbe3..46c3438942 100644 --- a/custom/languages/sv_SE.json +++ b/modules/Core/language/sv_SE.json @@ -1079,7 +1079,7 @@ "admin/delete_hook": "Är du säker på att du vill radera denna hook?", "admin/editing_integration_for_x": "Ändrar {{integration}} integrationen för {{user}}", "admin/editing_integration_x": "Ändrar integrationen {{integration}}", - "admin/email_language_info": "Ser inte ditt språk? Dubbelkolla att språk-filen är skrivbar av din webbserver i /custom/languages/.", + "admin/email_language_info": "Ser inte ditt språk? Dubbelkolla att språk-filen är skrivbar av din webbserver i /modules/Core/language/.", "admin/integration": "Integration", "admin/oauth_info": "Konfigurera OAuth-leverantörerna för att tillåta användare att logga in med deras sociala nätverks-konton. {{docLinkStart}}Kolla våran dokumentation för hjälp{{docLinkEnd}}.", "admin/page": "Sida", diff --git a/custom/languages/th_TH.json b/modules/Core/language/th_TH.json similarity index 100% rename from custom/languages/th_TH.json rename to modules/Core/language/th_TH.json diff --git a/custom/languages/tr_TR.json b/modules/Core/language/tr_TR.json similarity index 99% rename from custom/languages/tr_TR.json rename to modules/Core/language/tr_TR.json index 59a7e603b6..341fd95dd3 100644 --- a/custom/languages/tr_TR.json +++ b/modules/Core/language/tr_TR.json @@ -915,7 +915,7 @@ "admin/announcements": "Duyurular", "admin/api_endpoints": "API uç noktası", "admin/hooks": "Webhooklar", - "admin/email_language_info": "Dilinizi görmüyor musunuz? Dil dosyasının web sunucunuz tarafından /custom/languages/ içinde yazılabilir olduğundan emin olun.", + "admin/email_language_info": "Dilinizi görmüyor musunuz? Dil dosyasının web sunucunuz tarafından /modules/Core/language/ içinde yazılabilir olduğundan emin olun.", "emails/forum_topic_reply_message": "{{author}}, takip ettiğiniz bir konuyu yanıtladı. İçerik: {{content}}", "general/red": "Kırmızı", "installer/step_conversion": "Dönüştür", diff --git a/custom/languages/uk_UA.json b/modules/Core/language/uk_UA.json similarity index 100% rename from custom/languages/uk_UA.json rename to modules/Core/language/uk_UA.json diff --git a/custom/languages/vi_VN.json b/modules/Core/language/vi_VN.json similarity index 99% rename from custom/languages/vi_VN.json rename to modules/Core/language/vi_VN.json index 0be0acbbde..1455c8fa3e 100644 --- a/custom/languages/vi_VN.json +++ b/modules/Core/language/vi_VN.json @@ -165,7 +165,7 @@ "admin/email_errors": "Lỗi email", "admin/email_errors_logged": "Lỗi email đã được ghi lại", "admin/email_errors_purged_successfully": "Lỗi email đã được xóa thành công.", - "admin/email_language_info": "Bạn không thấy ngôn ngữ của mình? Đảm bảo rằng tệp ngôn ngữ có thể ghi trên webserver của bạn trong /custom/languages/.", + "admin/email_language_info": "Bạn không thấy ngôn ngữ của mình? Đảm bảo rằng tệp ngôn ngữ có thể ghi trên webserver của bạn trong /modules/Core/language/.", "admin/email_logs": "Email hàng loạt", "admin/email_message_greeting": "Lời chào", "admin/email_message_message": "Tin nhắn", diff --git a/custom/languages/zh_CN.json b/modules/Core/language/zh_CN.json similarity index 99% rename from custom/languages/zh_CN.json rename to modules/Core/language/zh_CN.json index ea201f7eae..cf204d3a82 100644 --- a/custom/languages/zh_CN.json +++ b/modules/Core/language/zh_CN.json @@ -1079,7 +1079,7 @@ "admin/custom_content": "自定义内容", "admin/editing_integration_for_x": "正在修改 {{user}} 的 {{integration}} 集成", "admin/editing_integration_x": "正在修改 {{integration}} 集成", - "admin/email_language_info": "找不到你的语言? 请确保在 /custom/languages 目录中的语言文件可写。", + "admin/email_language_info": "找不到你的语言? 请确保在 /modules/Core/language 目录中的语言文件可写。", "admin/favicon_image_x": "Favicon 图片: {{imageName}}", "admin/group_cloned_successfully": "成功复制了群组。", "admin/home_custom_content": "主页自定义内容", diff --git a/custom/languages/zh_TW.json b/modules/Core/language/zh_TW.json similarity index 100% rename from custom/languages/zh_TW.json rename to modules/Core/language/zh_TW.json diff --git a/modules/Core/pages/oauth.php b/modules/Core/pages/oauth.php index c1af0e3df2..4e5961aa94 100644 --- a/modules/Core/pages/oauth.php +++ b/modules/Core/pages/oauth.php @@ -179,7 +179,11 @@ // Link the user integration $integration->successfulRegistration($user); + if ($integration->getErrors()) { + Session::flash('connections_error', $integration->getErrors()[0]); + } + Session::delete('oauth_register_data'); Session::delete('oauth_method'); Redirect::to(URL::build('/user/connections')); -} +} \ No newline at end of file diff --git a/modules/Core/pages/panel/auth.php b/modules/Core/pages/panel/auth.php index 00656ef3a2..4eda3c571b 100644 --- a/modules/Core/pages/panel/auth.php +++ b/modules/Core/pages/panel/auth.php @@ -41,24 +41,44 @@ if ($validation->passed()) { $user = new User(); - $login = $user->adminLogin($user->data()->email, Input::get('password'), 'email'); - if ($login) { - // Get IP - $ip = HttpUtils::getRemoteAddress(); + if ($user->checkCredentials($user->data()->email, Input::get('password'))) { + $success = true; - // Create log - Log::getInstance()->log(Log::Action('admin/login')); + if ( + Settings::get('require_staffcp_tfa') && + $user->data()->tfa_type === 1 && + $user->data()->tfa_complete == 1 + ) { + $success = false; + $tfa = new \RobThree\Auth\TwoFactorAuth('NamelessMC'); - // Redirect to a certain page? - if (isset($_SESSION['last_page']) && substr($_SESSION['last_page'], -1) != '=') { - Redirect::back(); - } else { - Redirect::to(URL::build('/panel')); + if ($tfa->verifyCode($user->data()->tfa_secret, str_replace(' ', '', $_POST['tfa_code'])) !== true) { + Session::flash('adm_auth_error', $language->get('user', 'invalid_tfa')); + } else { + $success = true; + } } - } - Session::flash('adm_auth_error', $language->get('user', 'incorrect_details')); + if ($success) { + // Get IP + $ip = HttpUtils::getRemoteAddress(); + + // Create log + Log::getInstance()->log(Log::Action('admin/login')); + + $user->adminLogin($user->data()->email, Input::get('password')); + + // Redirect to a certain page? + if (isset($_SESSION['last_page']) && substr($_SESSION['last_page'], -1) != '=') { + Redirect::back(); + } else { + Redirect::to(URL::build('/panel')); + } + } + } else { + Session::flash('adm_auth_error', $language->get('user', 'incorrect_details')); + } } else { Session::flash('adm_auth_error', $language->get('user', 'incorrect_details')); } @@ -76,6 +96,17 @@ 'CANCEL' => $language->get('general', 'cancel') ]); +if ( + Settings::get('require_staffcp_tfa') && + $user->data()->tfa_type === 1 && + $user->data()->tfa_complete == 1 +) { + $smarty->assign([ + 'TWO_FACTOR_AUTH' => $language->get('user', 'two_factor_auth'), + 'TFA_ENTER_CODE' => $language->get('user', 'two_factor_auth_code'), + ]); +} + if (Session::exists('adm_auth_error')) { $smarty->assign('ERROR', Session::flash('adm_auth_error')); } diff --git a/modules/Core/pages/panel/general_settings.php b/modules/Core/pages/panel/general_settings.php index bebd0a7afb..a999da77af 100644 --- a/modules/Core/pages/panel/general_settings.php +++ b/modules/Core/pages/panel/general_settings.php @@ -165,6 +165,9 @@ // Auto language Settings::set('auto_language_detection', $_POST['auto_language'] === 'true' ? 1 : 0); + // StaffCP two-factor auth + Settings::set('require_staffcp_tfa', $_POST['require_staffcp_tfa'] === 'true' ? 1 : 0); + Log::getInstance()->log(Log::Action('admin/core/general')); Session::flash('general_language', $language->get('admin', 'settings_updated_successfully')); @@ -294,6 +297,8 @@ 'AUTO_LANGUAGE_VALUE' => Settings::get('auto_language_detection'), 'ENABLE_AUTO_LANGUAGE' => $language->get('admin', 'enable_auto_language'), 'AUTO_LANGUAGE_HELP' => $language->get('admin', 'auto_language_help'), + 'REQUIRE_STAFFCP_TFA' => $language->get('admin', 'require_two_factor_for_staffcp'), + 'REQUIRE_STAFFCP_TFA_VALUE' => Settings::get('require_staffcp_tfa'), ]); $template->onPageLoad(); diff --git a/modules/Core/queries/reactions.php b/modules/Core/queries/reactions.php index ed465bf28d..6e6fac8a9a 100644 --- a/modules/Core/queries/reactions.php +++ b/modules/Core/queries/reactions.php @@ -5,7 +5,7 @@ // Validate form input if ($_SERVER['REQUEST_METHOD'] === 'GET') { if (!isset($_GET['reactable_id']) || !is_numeric($_GET['reactable_id'])) { - http_response_code(400); + http_response_code(\Symfony\Component\HttpFoundation\Response::HTTP_BAD_REQUEST); die('Invalid input'); } $reactable_id = $_GET['reactable_id']; @@ -13,12 +13,12 @@ } else { // User must be logged in to proceed if (!$user->isLoggedIn()) { - http_response_code(401); + http_response_code(\Symfony\Component\HttpFoundation\Response::HTTP_UNAUTHORIZED); die('Not logged in'); } if (!isset($_POST['reactable_id'], $_POST['reaction_id']) || !is_numeric($_POST['reactable_id']) || !is_numeric($_POST['reaction_id'])) { - http_response_code(400); + http_response_code(\Symfony\Component\HttpFoundation\Response::HTTP_BAD_REQUEST); die('Invalid input'); } $reactable_id = $_POST['reactable_id']; @@ -28,14 +28,14 @@ $reaction_context = ReactionContextsManager::getInstance()->getContext($context); if (!$reaction_context->isEnabled()) { - http_response_code(400); + http_response_code(\Symfony\Component\HttpFoundation\Response::HTTP_BAD_REQUEST); die('Reactions disabled in this context'); } // Ensure exists $reactable = $reaction_context->validateReactable($reactable_id, $user); if (!$reactable) { - http_response_code(400); + http_response_code(\Symfony\Component\HttpFoundation\Response::HTTP_BAD_REQUEST); die('Invalid reactable'); } @@ -131,7 +131,7 @@ // add reaction if (!Token::check()) { - http_response_code(400); + http_response_code(\Symfony\Component\HttpFoundation\Response::HTTP_BAD_REQUEST); die('Invalid token'); } @@ -145,7 +145,7 @@ $reaction_context->name(), )); - http_response_code(200); + http_response_code(\Symfony\Component\HttpFoundation\Response::HTTP_OK); die('Reaction deleted'); } @@ -158,5 +158,5 @@ $reaction_context->name(), )); -http_response_code(200); +http_response_code(\Symfony\Component\HttpFoundation\Response::HTTP_OK); die('Reaction added'); diff --git a/modules/Core/queries/tinymce_image_upload.php b/modules/Core/queries/tinymce_image_upload.php index ac68eb0053..ea1e951f6e 100644 --- a/modules/Core/queries/tinymce_image_upload.php +++ b/modules/Core/queries/tinymce_image_upload.php @@ -1,12 +1,12 @@ isLoggedIn()) { - http_response_code(400); + http_response_code(\Symfony\Component\HttpFoundation\Response::HTTP_UNAUTHORIZED); die('Not logged in'); } if (!Token::check()) { - http_response_code(400); + http_response_code(\Symfony\Component\HttpFoundation\Response::HTTP_BAD_REQUEST); die('Invalid token'); } @@ -18,7 +18,7 @@ if ($image['file']) { if (!$image->upload()) { - http_response_code(500); + http_response_code(\Symfony\Component\HttpFoundation\Response::HTTP_INTERNAL_SERVER_ERROR); $error = $image->getError() ?: 'Unknown error, check logs for more details'; ErrorHandler::logWarning('TinyMCE image upload error: ' . $error); die($error); @@ -29,5 +29,5 @@ ])); } -http_response_code(400); +http_response_code(\Symfony\Component\HttpFoundation\Response::HTTP_BAD_REQUEST); die('No file uploaded'); diff --git a/modules/Discord Integration/includes/endpoints/SubmitDiscordRoleListEndpoint.php b/modules/Discord Integration/includes/endpoints/SubmitDiscordRoleListEndpoint.php index b8a5f5bd46..b960c71d9f 100644 --- a/modules/Discord Integration/includes/endpoints/SubmitDiscordRoleListEndpoint.php +++ b/modules/Discord Integration/includes/endpoints/SubmitDiscordRoleListEndpoint.php @@ -1,4 +1,5 @@ throwError(DiscordApiErrors::ERROR_UNABLE_TO_UPDATE_DISCORD_ROLES, $e->getMessage(), 500); + $api->throwError(DiscordApiErrors::ERROR_UNABLE_TO_UPDATE_DISCORD_ROLES, $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR); } $api->returnArray(['message' => Discord::getLanguageTerm('discord_settings_updated')]); diff --git a/modules/Discord Integration/includes/endpoints/UpdateDiscordBotSettingsEndpoint.php b/modules/Discord Integration/includes/endpoints/UpdateDiscordBotSettingsEndpoint.php index 640b1cbdb0..5ad2d1e682 100644 --- a/modules/Discord Integration/includes/endpoints/UpdateDiscordBotSettingsEndpoint.php +++ b/modules/Discord Integration/includes/endpoints/UpdateDiscordBotSettingsEndpoint.php @@ -1,4 +1,5 @@ throwError(DiscordApiErrors::ERROR_UNABLE_TO_SET_DISCORD_BOT_URL, $e->getMessage(), 500); + $api->throwError(DiscordApiErrors::ERROR_UNABLE_TO_SET_DISCORD_BOT_URL, $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR); } } @@ -28,7 +29,7 @@ public function execute(Nameless2API $api): void { try { Settings::set('discord', $_POST['guild_id']); } catch (Exception $e) { - $api->throwError(DiscordApiErrors::ERROR_UNABLE_TO_SET_DISCORD_GUILD_ID, $e->getMessage(), 500); + $api->throwError(DiscordApiErrors::ERROR_UNABLE_TO_SET_DISCORD_GUILD_ID, $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR); } } @@ -36,7 +37,7 @@ public function execute(Nameless2API $api): void { try { Settings::set('discord_bot_username', $_POST['bot_username']); } catch (Exception $e) { - $api->throwError(DiscordApiErrors::ERROR_UNABLE_TO_SET_DISCORD_BOT_USERNAME, $e->getMessage(), 500); + $api->throwError(DiscordApiErrors::ERROR_UNABLE_TO_SET_DISCORD_BOT_USERNAME, $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR); } } diff --git a/modules/Discord Integration/includes/endpoints/UpdateDiscordUsernames.php b/modules/Discord Integration/includes/endpoints/UpdateDiscordUsernames.php index 502530b7a1..c3470d89e3 100644 --- a/modules/Discord Integration/includes/endpoints/UpdateDiscordUsernames.php +++ b/modules/Discord Integration/includes/endpoints/UpdateDiscordUsernames.php @@ -1,4 +1,5 @@ Discord username to update @@ -35,7 +36,7 @@ public function execute(Nameless2API $api): void { } } } catch (Exception $e) { - $api->throwError(DiscordApiErrors::ERROR_UNABLE_TO_SET_DISCORD_BOT_USERNAME, $e->getMessage(), 500); + $api->throwError(DiscordApiErrors::ERROR_UNABLE_TO_SET_DISCORD_BOT_USERNAME, $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR); } $api->returnArray(['message' => Discord::getLanguageTerm('discord_usernames_updated'), 'updated_users' => $updated]); diff --git a/modules/Forum/classes/Forum.php b/modules/Forum/classes/Forum.php index 7cdf4a57ef..6fd4c24b03 100644 --- a/modules/Forum/classes/Forum.php +++ b/modules/Forum/classes/Forum.php @@ -798,6 +798,16 @@ public static function getAccessibleLabels(array $labels, array $user_groups): a }, []); } + /** + * Get banned terms from the Forum module + * + * @return array Array of banned terms + */ + public static function getBannedTerms(): array { + $terms = Settings::get('banned_terms', '', 'forum'); + return explode("\n", $terms); + } + /** * Get the latest post in a "View own topic" forum * This could be a topic created by the user, or a sticky topic diff --git a/modules/Forum/language/cs_CZ.json b/modules/Forum/language/cs_CZ.json index aeccee1863..481b595625 100644 --- a/modules/Forum/language/cs_CZ.json +++ b/modules/Forum/language/cs_CZ.json @@ -4,7 +4,7 @@ "forum/average_posts": "Průměrný počet příspěvků uživatele", "forum/by": "od", "forum/can_create_topic": "Může vytvářet témata?", - "forum/can_edit_topic": "Může upravovat svá témata??", + "forum/can_edit_topic": "Může upravovat svá témata?", "forum/can_moderate_forum": "Může moderovat fórum?", "forum/can_post_reply": "Může vytvářet odpovědi?", "forum/can_view_forum": "Může zobrazit fórum?", @@ -121,7 +121,7 @@ "forum/quote": "Citát", "forum/quoted_post": "Příspěvek citován", "forum/re": "RE: ", - "forum/read_full_post": "Přečtěte si celý příspěvek", + "forum/read_full_post": "Přečíst celý příspěvek", "forum/recent_posts": "Poslední příspěvky", "forum/recent_topics": "Poslední témata", "forum/redirect_forum": "Přesměrovat fórum?", @@ -150,7 +150,7 @@ "forum/topic_stuck": "Téma bylo připnuto.", "forum/topic_title": "Název tématu", "forum/topic_unstuck": "Téma bylo odepnuto.", - "forum/topics": "témat", + "forum/topics": "témata", "forum/topics_title": "Témata", "forum/total_posts": "Celkový počet příspěvků", "forum/unfollow": "Přestat sledovat", diff --git a/modules/Forum/language/en_UK.json b/modules/Forum/language/en_UK.json index 4eca0ffc7f..6cfb603190 100644 --- a/modules/Forum/language/en_UK.json +++ b/modules/Forum/language/en_UK.json @@ -3,6 +3,8 @@ "forum/available_hooks": "Available Hooks", "forum/average_posts": "Average user post count", "forum/topic_reply": "Topic reply", + "forum/banned_terms": "Banned Terms", + "forum/banned_terms_info": "One term per line, case insensitive", "forum/by": "by", "forum/can_create_topic": "Can create topics?", "forum/can_edit_topic": "Can edit their topics?", @@ -13,6 +15,7 @@ "forum/confirm_delete_post": "Are you sure you want to delete this post?", "forum/confirm_delete_topic": "Are you sure you want to delete this topic?", "forum/confirm_unfollow_all_topics": "Are you sure you want to unfollow all topics?", + "forum/content_contains_banned_term": "Your post content contains a banned term", "forum/content_max_50000": "Your post content must be no longer than 50.000 characters", "forum/content_min_2": "Your post content must be a minimum of 2 characters", "forum/content_required": "Please input post content", diff --git a/modules/Forum/language/es_ES.json b/modules/Forum/language/es_ES.json index 9fabce2191..a33959810d 100644 --- a/modules/Forum/language/es_ES.json +++ b/modules/Forum/language/es_ES.json @@ -179,9 +179,10 @@ "forum/latest_posts_limit": "Límite de las últimas publicaciones", "forum/no_posts_found": "No se encontraron publicaciones.", "forum/most_posts": "Más publicaciones", - "forum/highest_reaction_scores": "Puntuaciones de reacciones más altas", + "forum/highest_reaction_scores": "Puntuaciones más altas de reacciones en el foro", "forum/reaction_score": "Puntuación de reacción", "forum/news_items_front_page_limit": "Número de noticias a mostrar en la página principal", "forum/news_items_max": "El número de noticias debe ser al menos {{max}}", - "forum/news_items_min": "El número de noticias debe ser como mínimo {{min}}" + "forum/news_items_min": "El número de noticias debe ser como mínimo {{min}}", + "forum/forum_score": "Puntuación en el foro" } diff --git a/modules/Forum/language/zh_CN.json b/modules/Forum/language/zh_CN.json index 1b4a0486d4..2a009b016b 100644 --- a/modules/Forum/language/zh_CN.json +++ b/modules/Forum/language/zh_CN.json @@ -53,8 +53,8 @@ "forum/input_forum_title": "请输入一个论坛标题。", "forum/insert_quotes": "插入引用", "forum/invalid_action": "无效的行为", - "forum/invalid_redirect_url": "你已经启用了论坛重定向,但你的URL并不是有效的 1 到 512 个字符之间。", - "forum/invalid_search_query": "请输入一个在 3 和 128 个字符长度之间的关键词。", + "forum/invalid_redirect_url": "你已经启用了论坛重定向,但你的URL并不是有效的 {{min}}到 {{max}} 个字符之间。", + "forum/invalid_search_query": "请输入一个在 {{min}}和 {{max}}个字符长度之间的关键词。", "forum/label": "标签", "forum/label_creation_error": "创建标签时遇到了错误。 请确保名称没有超过 32 个字符并且你已指定了一个种类。", "forum/label_creation_success": "标签创建成功。", diff --git a/modules/Forum/pages/forum/edit.php b/modules/Forum/pages/forum/edit.php index 617247423d..55e5f4ffa9 100644 --- a/modules/Forum/pages/forum/edit.php +++ b/modules/Forum/pages/forum/edit.php @@ -85,7 +85,8 @@ 'content' => [ Validate::REQUIRED => true, Validate::MIN => 2, - Validate::MAX => 50000 + Validate::MAX => 50000, + Validate::NOT_CONTAIN => Forum::getBannedTerms(), ] ]; // Add title to validation if we need to @@ -101,7 +102,8 @@ 'content' => [ Validate::REQUIRED => $forum_language->get('forum', 'content_required'), Validate::MIN => $forum_language->get('forum', 'content_min_2'), - Validate::MAX => $forum_language->get('forum', 'content_max_50000') + Validate::MAX => $forum_language->get('forum', 'content_max_50000'), + Validate::NOT_CONTAIN => $forum_language->get('forum', 'content_contains_banned_term'), ], 'title' => [ Validate::REQUIRED => $forum_language->get('forum', 'title_required'), diff --git a/modules/Forum/pages/forum/new_topic.php b/modules/Forum/pages/forum/new_topic.php index 85d6733bf3..64253e809b 100644 --- a/modules/Forum/pages/forum/new_topic.php +++ b/modules/Forum/pages/forum/new_topic.php @@ -112,7 +112,8 @@ 'content' => [ Validate::REQUIRED => true, Validate::MIN => 2, - Validate::MAX => 50000 + Validate::MAX => 50000, + Validate::NOT_CONTAIN => Forum::getBannedTerms(), ] ])->messages([ 'title' => [ @@ -123,7 +124,8 @@ 'content' => [ Validate::REQUIRED => $forum_language->get('forum', 'content_required'), Validate::MIN => $forum_language->get('forum', 'content_min_2'), - Validate::MAX => $forum_language->get('forum', 'content_max_50000') + Validate::MAX => $forum_language->get('forum', 'content_max_50000'), + Validate::NOT_CONTAIN => $forum_language->get('forum', 'content_contains_banned_term'), ] ]); diff --git a/modules/Forum/pages/forum/spam.php b/modules/Forum/pages/forum/spam.php index 6bf9df815d..fd165dcb99 100644 --- a/modules/Forum/pages/forum/spam.php +++ b/modules/Forum/pages/forum/spam.php @@ -49,10 +49,13 @@ } // First get any forums where this user is the last user who posted - $latest_forums = []; + $latest_forums = [$post->forum_id]; $latest_forums_query = DB::getInstance()->query('SELECT `id` FROM nl2_forums WHERE `last_user_posted` = ?', [$banned_user->data()->id]); if ($latest_forums_query->count()) { $latest_forums = array_map(fn($latest_forum) => $latest_forum->id, $latest_forums_query->results()); + if (!in_array($post->forum_id, $latest_forums)) { + $latest_forums[] = $post->forum_id; + } } // Now get any topics where this user is the last user who posted diff --git a/modules/Forum/pages/forum/view_topic.php b/modules/Forum/pages/forum/view_topic.php index 9a4c38a0d7..345904bbb1 100644 --- a/modules/Forum/pages/forum/view_topic.php +++ b/modules/Forum/pages/forum/view_topic.php @@ -248,13 +248,15 @@ 'content' => [ Validate::REQUIRED => true, Validate::MIN => 2, - Validate::MAX => 50000 + Validate::MAX => 50000, + Validate::NOT_CONTAIN => Forum::getBannedTerms(), ] ])->messages([ 'content' => [ Validate::REQUIRED => $forum_language->get('forum', 'content_required'), Validate::MIN => $forum_language->get('forum', 'content_min_2'), - Validate::MAX => $forum_language->get('forum', 'content_max_50000') + Validate::MAX => $forum_language->get('forum', 'content_max_50000'), + Validate::NOT_CONTAIN => $forum_language->get('forum', 'content_contains_banned_term'), ] ]); diff --git a/modules/Forum/pages/panel/settings.php b/modules/Forum/pages/panel/settings.php index da82c018c5..679fb8578d 100644 --- a/modules/Forum/pages/panel/settings.php +++ b/modules/Forum/pages/panel/settings.php @@ -58,6 +58,7 @@ Settings::set('forum_reactions', (isset($_POST['use_reactions']) && $_POST['use_reactions'] == 'on') ? '1' : 0); Settings::set('news_items_front_page', $_POST['news_items'], 'forum'); + Settings::set('banned_terms', $_POST['banned_terms'], 'forum'); Session::flash('admin_forums_settings', $forum_language->get('forum', 'settings_updated_successfully')); } else { @@ -114,6 +115,10 @@ 'USE_REACTIONS_VALUE' => Settings::get('forum_reactions') === '1', 'NEWS_ITEMS_ON_FRONT_PAGE' => $forum_language->get('forum', 'news_items_front_page_limit'), 'NEWS_ITEMS_ON_FRONT_PAGE_VALUE' => Settings::get('news_items_front_page', 5, 'forum'), + 'BANNED_TERMS' => $forum_language->get('forum', 'banned_terms'), + 'BANNED_TERMS_INFO' => $forum_language->get('forum', 'banned_terms_info'), + 'BANNED_TERMS_VALUE' => Output::getClean(Settings::get('banned_terms', '', 'forum')), + 'INFO' => $language->get('general', 'info'), 'PAGE' => PANEL_PAGE, 'TOKEN' => Token::get(), 'SUBMIT' => $language->get('general', 'submit') diff --git a/modules/Members/language/zh_CN.json b/modules/Members/language/zh_CN.json index 0967ef424b..c76d036875 100644 --- a/modules/Members/language/zh_CN.json +++ b/modules/Members/language/zh_CN.json @@ -1 +1,19 @@ -{} +{ + "members/members": "成员", + "members/new_members": "新成员", + "members/no_members": "未找到成员。", + "members/member_lists": "成员列表", + "members/member_list_hide_banned_users": "隐藏被封禁的用户?", + "members/member_list_toggled_enabled": "成功启用了 {{list}} 列表。", + "members/member_list_toggled_disabled": "成功禁用了 {{list}} 列表。", + "members/view_all": "查看全部", + "members/find_member": "查找成员", + "members/viewable_groups": "可查看的组", + "members/no_results_header": "未找到结果", + "members/no_results_text": "你的搜索没有返回任何结果", + "members/no_overview_lists_enabled": "未启用概览列表。", + "members/settings_updated_successfully": "设置已成功更新。", + "members/name": "名称...", + "members/view_group": "查看成员列表", + "members/group": "组..." +} diff --git a/package-lock.json b/package-lock.json index 1b49233b63..7f53f35ed5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "nameless", - "version": "2.1.1", + "version": "2.1.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "nameless", - "version": "2.1.1", + "version": "2.1.2", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -29,7 +29,7 @@ "popper.js": "^1.16.1", "select2": "4.1.0-rc.0", "skinview3d": "^3.0.0-alpha.1", - "tinymce": "5.10.7" + "tinymce": "5.10.9" } }, "node_modules/@actions/core": { @@ -1913,13 +1913,14 @@ } }, "node_modules/es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", "hasInstallScript": true, "dependencies": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", "next-tick": "^1.1.0" }, "engines": { @@ -1972,6 +1973,34 @@ "node": ">=0.8.0" } }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esniff/node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "node_modules/execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", @@ -5334,9 +5363,15 @@ "optional": true }, "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -6144,9 +6179,9 @@ } }, "node_modules/postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", @@ -6155,10 +6190,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -7539,9 +7578,9 @@ } }, "node_modules/tinymce": { - "version": "5.10.7", - "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-5.10.7.tgz", - "integrity": "sha512-9UUjaO0R7FxcFo0oxnd1lMs7H+D0Eh+dDVo5hKbVe1a+VB0nit97vOqlinj+YwgoBDt6/DSCUoWqAYlLI8BLYA==" + "version": "5.10.9", + "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-5.10.9.tgz", + "integrity": "sha512-5bkrors87X9LhYX2xq8GgPHrIgJYHl87YNs+kBcjQ5I3CiUgzo/vFcGvT3MZQ9QHsEeYMhYO6a5CLGGffR8hMg==" }, "node_modules/tmp": { "version": "0.0.33", @@ -9827,12 +9866,13 @@ } }, "es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", "requires": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", "next-tick": "^1.1.0" } }, @@ -9876,6 +9916,33 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" }, + "esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "dependencies": { + "type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + } + } + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", @@ -12571,9 +12638,9 @@ "optional": true }, "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" }, "nanomatch": { "version": "1.2.13", @@ -13147,11 +13214,11 @@ "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==" }, "postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "requires": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } @@ -14243,9 +14310,9 @@ "integrity": "sha512-gLCeArryy2yNTRzTGKbZbloctj64jkZ57hj5zdraXue6aFgd6PmvVtEyiUU+hvU0v7q08oVv8r8ev0tRo6bvgw==" }, "tinymce": { - "version": "5.10.7", - "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-5.10.7.tgz", - "integrity": "sha512-9UUjaO0R7FxcFo0oxnd1lMs7H+D0Eh+dDVo5hKbVe1a+VB0nit97vOqlinj+YwgoBDt6/DSCUoWqAYlLI8BLYA==" + "version": "5.10.9", + "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-5.10.9.tgz", + "integrity": "sha512-5bkrors87X9LhYX2xq8GgPHrIgJYHl87YNs+kBcjQ5I3CiUgzo/vFcGvT3MZQ9QHsEeYMhYO6a5CLGGffR8hMg==" }, "tmp": { "version": "0.0.33", diff --git a/package.json b/package.json index 01273cc81e..b62364abcd 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "popper.js": "^1.16.1", "select2": "4.1.0-rc.0", "skinview3d": "^3.0.0-alpha.1", - "tinymce": "5.10.7" + "tinymce": "5.10.9" }, "scripts": { "postinstall": "node ./dev/scripts/postinstall.js"