diff --git a/Web/Presenters/AdminPresenter.php b/Web/Presenters/AdminPresenter.php
index ff21612b..4a52c0e8 100644
--- a/Web/Presenters/AdminPresenter.php
+++ b/Web/Presenters/AdminPresenter.php
@@ -550,4 +550,84 @@ final class AdminPresenter extends OpenVKPresenter
$this->redirect("/admin/users/id" . $user->getId());
}
+
+ function renderTuning(): void
+ {
+ $mode = in_array($this->queryParam("act"), ["cfg"]) ? $this->queryParam("act") : "cfg";
+
+ if ($_SERVER["REQUEST_METHOD"] === "POST") {
+ $this->assertNoCSRF();
+ if ($mode === "cfg") {
+ $yaml = $this->postParam("yaml");
+ if (!$yaml)
+ $this->notFound();
+
+ $temp_file_path = __DIR__ . "../../../openvk." . time() . ".yml";
+ $temp_file = fopen($temp_file_path, "x");
+ if ($temp_file) {
+ if (fwrite($temp_file, $this->postParam("yaml"))) {
+ $temp_file_content = file_get_contents($temp_file_path);
+ if ($temp_file_content) {
+ if (chandler_parse_yaml($temp_file_path)) {
+ if (rename(__DIR__ . "../../../openvk.yml", __DIR__ . "../../../openvk.yml.tmp")) {
+ $cfg_file = fopen(__DIR__ . "../../../openvk.yml", "x");
+ if ($cfg_file) {
+ if (file_put_contents(__DIR__ . "../../../openvk.yml", $temp_file_content)) {
+ unlink(__DIR__ . "../../../openvk.yml.tmp");
+ unlink($temp_file_path);
+ $this->returnJson(["success" => true]);
+ } else {
+ $this->returnJson(["success" => false, "error" => tr("admin_tuning_cfg_write_fail")]);
+ }
+ } else {
+ $this->returnJson(["success" => false, "error" => tr("admin_tuning_cfg_create_fail")]);
+ }
+ } else {
+ $this->returnJson(["success" => false, "error" => tr("admin_tuning_cfg_create_fail")]);
+ }
+ } else {
+ $this->returnJson(["success" => false, "error" => tr("admin_tuning_cfg_tmp_read_fail_yaml")]);
+ }
+ } else {
+ $this->returnJson(["success" => false, "error" => tr("admin_tuning_cfg_tmp_read_fail")]);
+ }
+ } else {
+ $this->returnJson(["success" => false, "error" => tr("admin_tuning_cfg_file_write_err")]);
+ }
+ } else {
+ $this->returnJson(["success" => false, "error" => tr("admin_tuning_cfg_file_create_err")]);
+ }
+ }
+ } else {
+ $this->template->mode = $mode;
+
+ if ($mode === "cfg") {
+ $file_path = __DIR__ . "../../../openvk.yml";
+ if (file_exists($file_path)) {
+ $this->template->cfg = chandler_parse_yaml($file_path);
+ } else if (file_exists(__DIR__ . "../../../openvk-example.yml")) {
+ $this->flash("warn", tr("admin_tuning_cfg_not_found"), tr("admin_tuning_cfg_not_found_description"));
+ $this->template->cfg = chandler_parse_yaml(__DIR__ . "../../../openvk-example.yml");
+ } else {
+ $repo_file = file_get_contents("https://raw.githubusercontent.com/openvk/openvk/master/openvk-example.yml");
+ if ($repo_file) {
+ $file = fopen($file_path, "x");
+ if ($file) {
+ if (fwrite($file, $repo_file)) {
+ fclose($file);
+ $this->template->cfg = chandler_parse_yaml($file_path);
+ } else {
+ fclose($file);
+ $this->flash("err", tr("admin_tuning_cfg_file_write_err"), tr("admin_tuning_cfg_error_description"));
+ }
+ } else {
+ $this->flash("err", tr("admin_tuning_cfg_file_create_err"), tr("admin_tuning_cfg_error_description"));
+ }
+ } else {
+ $this->flash("err", tr("admin_tuning_cfg_file_not_found_in_repo"), tr("admin_tuning_cfg_error_description"));
+ }
+ }
+ }
+ }
+ }
}
diff --git a/Web/Presenters/templates/Admin/Tuning.xml b/Web/Presenters/templates/Admin/Tuning.xml
new file mode 100644
index 00000000..871e6630
--- /dev/null
+++ b/Web/Presenters/templates/Admin/Tuning.xml
@@ -0,0 +1,43 @@
+{extends "@layout.xml"}
+
+{block title}
+ {_admin_settings_tuning}
+{/block}
+
+{block heading}
+ {include title}
+{/block}
+
+{block content}
+
+
+
+
+
+
+
+
+ {script "js/yaml.js"}
+{/block}
diff --git a/Web/Presenters/templates/Admin/displayYamlData.xml b/Web/Presenters/templates/Admin/displayYamlData.xml
new file mode 100644
index 00000000..b9f58099
--- /dev/null
+++ b/Web/Presenters/templates/Admin/displayYamlData.xml
@@ -0,0 +1,26 @@
+{block displayYamlData}
+ {foreach $cfg as $key => $value}
+ {var $level = 'h' . ($baseLevel + 1)}
+ {var $intLevel = $baseLevel + 1}
+ {var $indent = $intLevel * 10}
+
+ {/foreach}
+{/block}
diff --git a/Web/routes.yml b/Web/routes.yml
index d1a0e7ae..8deb7512 100644
--- a/Web/routes.yml
+++ b/Web/routes.yml
@@ -339,6 +339,8 @@ routes:
handler: "Admin->chandlerGroup"
- url: "/admin/chandler/users/{slug}"
handler: "Admin->chandlerUser"
+ - url: "/admin/settings/tuning"
+ handler: "Admin->tuning"
- url: "/internal/wall{num}"
handler: "Wall->wallEmbedded"
- url: "/robots.txt"
diff --git a/Web/static/js/yaml.js b/Web/static/js/yaml.js
new file mode 100644
index 00000000..02120b4a
--- /dev/null
+++ b/Web/static/js/yaml.js
@@ -0,0 +1,102 @@
+function convertFormToYAML(handler, csrfToken) {
+ const form = $(".aui");
+ let formData = [];
+
+ form.find('input, select').each(function () {
+ let key = $(this).attr("name");
+ let value = $(this).val();
+ let level = $(this).attr("level") ?? 0;
+
+ if ($(this).is('select')) {
+ value = (value === 'true');
+ }
+
+ if ($(this).attr("disabled")) {
+ return;
+ }
+
+ if ($(this).attr("noValue")) {
+ formData.push({indentation: level, key: key, value: value, noValue: true});
+ } else {
+ formData.push({indentation: level, key: key, value: value});
+ }
+ });
+
+ const yaml = restoreYAMLFromJS(formData);
+ $.ajax({
+ type: "POST",
+ url: handler,
+ data: {
+ yaml: yaml,
+ hash: csrfToken
+ },
+ success: (data) => {
+ if (data.success) {
+ window.location.reload();
+ } else {
+ alert(tr("error") + ': ' + data.error);
+ }
+ }
+ })
+}
+
+function restoreYAMLFromJS(formData) {
+ let yamlData = '';
+ let stack = [];
+ let currentIndent = 0;
+ let addDashForNextKey = false;
+ let nextSpacesOverride = null;
+
+ formData.forEach((_key, i) => {
+ let {indentation, key} = _key;
+ let value = _key.value;
+ const level = parseInt(indentation);
+
+ console.log(_key);
+
+ let spaces = ' '.repeat(nextSpacesOverride ?? (level * 4));
+ nextSpacesOverride = null;
+
+ while (level < currentIndent) {
+ stack.pop();
+ currentIndent -= 1;
+ }
+
+ if (_key?.noValue) {
+ yamlData += `${spaces}${key}:\n`;
+ } else {
+ if (/\d$/.test(key) && value.length === 0) {
+ addDashForNextKey = true;
+ } else {
+ if (addDashForNextKey) {
+ let _s = `${spaces}- ${key}: \"${value}\"\n`;
+ nextSpacesOverride = _s.split(key)[0].length;
+ yamlData += _s;
+ addDashForNextKey = false;
+ } else if (/\d: ".*"/.test(`${key}: \"${value}\"`)) {
+ yamlData += `${spaces}- ${value}\n`;
+ addDashForNextKey = false;
+ } else {
+ if (value.length === 0) {
+ yamlData += `${spaces}${key}: \"\"\n`;
+ } else if (typeof value === 'boolean') {
+ yamlData += `${spaces}${key}: ${value}\n`;
+ } else if (value === 'null' || value == " ") {
+ yamlData += `${spaces}${key}: null\n`;
+ } else if (value.startsWith('"') && value.endsWith('"')) {
+ yamlData += `${spaces}${key}: ${value}\n`;
+ } else {
+ yamlData += `${spaces}${key}: \"${value}\"\n`;
+ currentIndent = level + 1;
+
+ stack.push(yamlData);
+ stack.push(level + 1);
+ stack.push(key);
+ }
+ }
+ }
+ }
+ });
+
+ return yamlData;
+}
diff --git a/locales/by.strings b/locales/by.strings
index 74c59cbf..a701abc2 100644
--- a/locales/by.strings
+++ b/locales/by.strings
@@ -560,3 +560,16 @@
"closed_group_post" = "Гэта паведамленне з прыватнай групы";
"deleted_target_comment" = "Гэты каментарый належыць да выдаленага поста";
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
diff --git a/locales/by_lat.strings b/locales/by_lat.strings
index 55e84cd3..cc44ded4 100644
--- a/locales/by_lat.strings
+++ b/locales/by_lat.strings
@@ -520,3 +520,16 @@
"closed_group_post" = "Heta paviedamliennie z pryvatnaj hrupy";
"deleted_target_comment" = "Heta paviedamliennie z pryvatnaj hrupy";
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
diff --git a/locales/de.strings b/locales/de.strings
index 6ba9fdf7..f61dd7a5 100644
--- a/locales/de.strings
+++ b/locales/de.strings
@@ -505,3 +505,16 @@
"to_top" = "Nach oben";
"checkbox_in_registration" = "Ich stimme der Datenschutzpolitik und der Seitenpolitik zu.";
"access_recovery_info" = "Haben Sie Ihr Passwort vergessen? Kein Problem, geben Sie Ihre Daten ein und wir senden Ihnen eine E-Mail mit Anweisungen, wie Sie Ihr Konto wiederherstellen können.";
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
diff --git a/locales/en.strings b/locales/en.strings
index 4aaa4483..cf39b545 100644
--- a/locales/en.strings
+++ b/locales/en.strings
@@ -1537,3 +1537,121 @@
"mobile_like" = "Like";
"mobile_user_info_hide" = "Hide";
"mobile_user_info_show_details" = "Show details";
+
+"save_all" = "Save all";
+"admin_tuning_cfg_not_found" = "The file openvk.yml was not found";
+"admin_tuning_cfg_not_found_description" = "openvk-example.yml is used. The configuration will be applied after saving.";
+"admin_tuning_cfg_error_description" = "Create an openvk.yml file or download it from the repository";
+"admin_tuning_cfg_file_write_err" = "Configuration file could not be written, editing is blocked";
+"admin_tuning_cfg_file_create_err" = "Configuration file could not be created, editing is blocked";
+"admin_tuning_cfg_file_not_found_in_repo" = "Configuration file not found in repository, editing blocked";
+"admin_tuning_cfg_write_fail" = "Error writing a configuration file";
+"admin_tuning_cfg_create_fail" = "Error when creating a configuration file";
+"admin_tuning_cfg_tmp_read_fail_yaml" = "Error when reading temporary file: possibly incorrect YAML was passed";
+"admin_tuning_cfg_tmp_read_fail" = "Failed to read the temporary file";
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_debug" = "Debug mode";
+"admin_settings_tuning_appearance" = "Appearance";
+"admin_settings_tuning_name" = "Name";
+"admin_settings_tuning_motd" = "Instance description";
+"admin_settings_tuning_preferences" = "Settings";
+"admin_settings_tuning_femaleGenderPriority" = "Female gender priority";
+"admin_settings_tuning_nginxCacheTime" = "nginx Cache time";
+"admin_settings_tuning_uploads" = "Uploads";
+"admin_settings_tuning_disableLargeUploads" = "Disable large uploads";
+"admin_settings_tuning_mode" = "Mode";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_maxFilesPerDomain" = "Max files per domain";
+"admin_settings_tuning_maxFileSize" = "Max file size";
+"admin_settings_tuning_shortcodes" = "Shortcodes";
+"admin_settings_tuning_minLength" = "Min length";
+"admin_settings_tuning_forbiddenNames" = "Forbidden names";
+"admin_settings_tuning_array_element" = "Array Item";
+"admin_settings_tuning_photos" = "Photos";
+"admin_settings_tuning_upgradeStructure" = "Upgrade structure";
+"admin_settings_tuning_photoSaving" = "Photo saving";
+"admin_settings_tuning_videos" = "Videos";
+"admin_settings_tuning_disableUploading" = "Disable uploading";
+"admin_settings_tuning_apps" = "Apps";
+"admin_settings_tuning_withdrawTax" = "Withdraw tax";
+"admin_settings_tuning_security" = "Security";
+"admin_settings_tuning_requireEmail" = "Require Email";
+"admin_settings_tuning_requirePhone" = "Require phone";
+"admin_settings_tuning_forcePhoneVerification" = "Force phone verification";
+"admin_settings_tuning_forceEmailVerification" = "Force Email verification";
+"admin_settings_tuning_forceStrongPassword" = "Force strong password";
+"admin_settings_tuning_disablePasswordRestoring" = "Disable password restoring";
+"admin_settings_tuning_enableSu" = "Allow user substitution";
+"admin_settings_tuning_rateLimits" = "Rate limits";
+"admin_settings_tuning_actions" = "Actions";
+"admin_settings_tuning_time" = "Time";
+"admin_settings_tuning_maxViolations" = "Max violations";
+"admin_settings_tuning_maxViolationsAge" = "Max violations age";
+"admin_settings_tuning_autoban" = "Auto ban";
+"admin_settings_tuning_registration" = "Registration";
+"admin_settings_tuning_enable" = "Enable";
+"admin_settings_tuning_disablingReason" = "Disabling reason";
+"admin_settings_tuning_support" = "Support";
+"admin_settings_tuning_supportName" = "Default responder name";
+"admin_settings_tuning_adminAccount" = "Admin account";
+"admin_settings_tuning_messages" = "Messages";
+"admin_settings_tuning_wall" = "Wall";
+"admin_settings_tuning_anonymousPosting" = "Anonymous posting";
+"admin_settings_tuning_account" = "Account";
+"admin_settings_tuning_postSizes" = "Post sizes";
+"admin_settings_tuning_maxSize" = "Max size";
+"admin_settings_tuning_processingLimit" = "Предел обработки";
+"admin_settings_tuning_emojiProcessingLimit" = "Emoji processing limit";
+"admin_settings_tuning_commerce" = "Commerce enabled";
+"admin_settings_tuning_susLinks" = "Suspicious links";
+"admin_settings_tuning_warnings" = "Warnings";
+"admin_settings_tuning_showReason" = "Show the reason";
+"admin_settings_tuning_maintenanceMode" = "Maintenance";
+"admin_settings_tuning_all" = "All";
+"admin_settings_tuning_messenger" = "Messenger";
+"admin_settings_tuning_user" = "User";
+"admin_settings_tuning_group" = "Groups";
+"admin_settings_tuning_comment" = "Comments";
+"admin_settings_tuning_gifts" = "Gifts";
+"admin_settings_tuning_notes" = "Notes";
+"admin_settings_tuning_notification" = "Notifications";
+"admin_settings_tuning_topics" = "Topics";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_enabled" = "Enabled";
+"admin_settings_tuning_menu" = "Menu";
+"admin_settings_tuning_links" = "Links";
+"admin_settings_tuning_about" = "About";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_adPoster" = "Ad poster";
+"admin_settings_tuning_src" = "Source";
+"admin_settings_tuning_caption" = "Caption";
+"admin_settings_tuning_link" = "Link";
+"admin_settings_tuning_defaultMobileTheme" = "Default mobile theme";
+"admin_settings_tuning_telemetry" = "Telemetry";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_container" = "Container";
+"admin_settings_tuning_site" = "Site";
+"admin_settings_tuning_credentials" = "Credentials";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_client" = "Client";
+"admin_settings_tuning_layer" = "Layer";
+"admin_settings_tuning_secret" = "Secret key";
+"admin_settings_tuning_token" = "Token";
+"admin_settings_tuning_helpdeskChat" = "Helpdesk chat";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_database" = "Database";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_password" = "Password";
+"admin_settings_tuning_notificationsBroker" = "Notifications broker";
+"admin_settings_tuning_domain" = "Domain";
+"admin_settings_tuning_server" = "Server";
+"admin_settings_tuning_address" = "Address";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
+"admin_settings_tuning_hint" = "Hint";
+"admin_settings_tuning_addr" = "Address";
+"admin_settings_tuning_port" = "Port";
+"admin_settings_tuning_topic" = "Topic";
diff --git a/locales/eo.strings b/locales/eo.strings
index b57d998f..bfd7c732 100644
--- a/locales/eo.strings
+++ b/locales/eo.strings
@@ -673,4 +673,18 @@
"edit_action" = "Ŝanĝi";
"warning" = "Averto";
-"question_confirm" = "Ĉi tiu ago ne povas esti malfarita. Ĉu vi vere volas fari ĝin?";
\ No newline at end of file
+"question_confirm" = "Ĉi tiu ago ne povas esti malfarita. Ĉu vi vere volas fari ĝin?";
+
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
diff --git a/locales/hy.strings b/locales/hy.strings
index de11783f..bb8f7877 100644
--- a/locales/hy.strings
+++ b/locales/hy.strings
@@ -1214,3 +1214,16 @@
"undergoing_section_maintenance" = "Ցավոք սրտի, $1 բաժինը ժամանակավորապես անհասանելի է։ Մենք արդեն աշխատում ենք խնդիրները շտկելու ուղղությամբ։ Խնդրում ենք այցելել մի քիչ ուշ։";
"topics" = "Թեմաներ";
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
diff --git a/locales/id.strings b/locales/id.strings
index d0a43d19..1d3e94cd 100644
--- a/locales/id.strings
+++ b/locales/id.strings
@@ -878,3 +878,16 @@
/* User alerts */
"user_alert_scam" = "Akun ini telah banyak dilaporkan melakukan penipuan. Berhati-hatilah, terutama jika ia meminta uang.";
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
diff --git a/locales/kk.strings b/locales/kk.strings
index e3c08cae..09a2800a 100644
--- a/locales/kk.strings
+++ b/locales/kk.strings
@@ -1124,3 +1124,16 @@
"nt_you_were_mentioned_g" = "Сізді осы топ атап өтті:";
"backdrop_warn" = "Суреттер жоғарыдағы орналасудағыдай реттеледі. Олардың биіктігі автоматты түрде ұлғайып, экран биіктігінің 100% алады, ортасында бұлыңғырлық болады. Негізгі OpenVK интерфейсінің фонын ауыстыру немесе дыбысты қосу мүмкін емес.";
"gifts_left_zero" = "Нөл сыйлық қалды";
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
diff --git a/locales/pl.strings b/locales/pl.strings
index 1f58be30..079baaf9 100644
--- a/locales/pl.strings
+++ b/locales/pl.strings
@@ -849,3 +849,16 @@
/* User alerts */
"user_alert_scam" = "Wiele osób skarżyło się na to konto w związku z oszustwem. Zachowaj ostrożność, zwłaszcza jeśli zostaniesz poproszony o pieniądze.";
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
diff --git a/locales/qqx.strings b/locales/qqx.strings
index 98d329af..3b60b5b4 100644
--- a/locales/qqx.strings
+++ b/locales/qqx.strings
@@ -1 +1,14 @@
/* Used for viewing message keys */
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
diff --git a/locales/ru.strings b/locales/ru.strings
index 6faa5e2e..41608696 100644
--- a/locales/ru.strings
+++ b/locales/ru.strings
@@ -1430,3 +1430,121 @@
"mobile_like" = "Нравится";
"mobile_user_info_hide" = "Скрыть";
"mobile_user_info_show_details" = "Показать подробнее";
+
+"save_all" = "Сохранить все";
+"admin_tuning_cfg_not_found" = "Файл openvk.yml не найден";
+"admin_tuning_cfg_not_found" = "Используется openvk-example.yml. Конфигурация будет применена после сохранения.";
+"admin_tuning_cfg_error_description" = "Создайте файл openvk.yml или скачайте его из репозитория";
+"admin_tuning_cfg_file_write_err" = "Не удалось записать файл конфигурации, редактирование заблокировано";
+"admin_tuning_cfg_file_create_err" = "Не удалось создать файл конфигурации, редактирование заблокировано";
+"admin_tuning_cfg_file_not_found_in_repo" = "Файл с конфигурацией не найден в репозитории, редактирование заблокировано";
+"admin_tuning_cfg_write_fail" = "Ошибка при записи файла конфигурации";
+"admin_tuning_cfg_create_fail" = "Ошибка при создании файла конфигурации";
+"admin_tuning_cfg_tmp_read_fail_yaml" = "Ошибка при чтении временного файла: возможно, передан некорректный YAML";
+"admin_tuning_cfg_tmp_read_fail" = "Не удалось прочитать временный файл";
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_debug" = "Режим отладки";
+"admin_settings_tuning_appearance" = "Внешний вид";
+"admin_settings_tuning_name" = "Название";
+"admin_settings_tuning_motd" = "Описание инстанса";
+"admin_settings_tuning_preferences" = "Настройки";
+"admin_settings_tuning_femaleGenderPriority" = "Приоритет женского пола";
+"admin_settings_tuning_nginxCacheTime" = "Время кэширования nginx";
+"admin_settings_tuning_uploads" = "Загрузки";
+"admin_settings_tuning_disableLargeUploads" = "Отключить большие загрузки";
+"admin_settings_tuning_mode" = "Режим";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_maxFilesPerDomain" = "Максимальное количество файлов на домен";
+"admin_settings_tuning_maxFileSize" = "Максимальный размер файла";
+"admin_settings_tuning_shortcodes" = "Короткие адреса";
+"admin_settings_tuning_minLength" = "Минимальная длина";
+"admin_settings_tuning_forbiddenNames" = "Запрещенные значения";
+"admin_settings_tuning_array_element" = "Элемент списка";
+"admin_settings_tuning_photos" = "Фотографии";
+"admin_settings_tuning_upgradeStructure" = "Улучшение структуры";
+"admin_settings_tuning_photoSaving" = "Сохранение фото";
+"admin_settings_tuning_videos" = "Видео";
+"admin_settings_tuning_disableUploading" = "Отключить загрузку";
+"admin_settings_tuning_apps" = "Приложения";
+"admin_settings_tuning_withdrawTax" = "Комиссия на вывод";
+"admin_settings_tuning_security" = "Безопасность";
+"admin_settings_tuning_requireEmail" = "Требуется электронная почта";
+"admin_settings_tuning_requirePhone" = "Требуется номер телефона";
+"admin_settings_tuning_forcePhoneVerification" = "Принудительная верификация телефона";
+"admin_settings_tuning_forceEmailVerification" = "Принудительная проверка электронной почты";
+"admin_settings_tuning_forceStrongPassword" = "Принудительное использование надежного пароля";
+"admin_settings_tuning_disablePasswordRestoring" = "Отключить восстановление пароля";
+"admin_settings_tuning_enableSu" = "Включить замену пользователя";
+"admin_settings_tuning_rateLimits" = "Рейт-лимиты";
+"admin_settings_tuning_actions" = "Действия";
+"admin_settings_tuning_time" = "Время";
+"admin_settings_tuning_maxViolations" = "Максимальное количество нарушений";
+"admin_settings_tuning_maxViolationsAge" = "Максимальный возраст нарушений";
+"admin_settings_tuning_autoban" = "Автоматический бан";
+"admin_settings_tuning_registration" = "Регистрация";
+"admin_settings_tuning_enable" = "Включить";
+"admin_settings_tuning_disablingReason" = "Причина отключения";
+"admin_settings_tuning_support" = "Поддержка";
+"admin_settings_tuning_supportName" = "Имя отвечающего по умолчанию";
+"admin_settings_tuning_adminAccount" = "Аккаунт администратора";
+"admin_settings_tuning_messages" = "Сообщения";
+"admin_settings_tuning_wall" = "Стена";
+"admin_settings_tuning_anonymousPosting" = "Анонимные публикации";
+"admin_settings_tuning_account" = "Аккаунт";
+"admin_settings_tuning_postSizes" = "Размеры постов";
+"admin_settings_tuning_maxSize" = "Максимальные размеры";
+"admin_settings_tuning_processingLimit" = "Предел обработки";
+"admin_settings_tuning_emojiProcessingLimit" = "Предел обработки Emoji";
+"admin_settings_tuning_commerce" = "Коммерция включена";
+"admin_settings_tuning_susLinks" = "Подозрительные ссылки";
+"admin_settings_tuning_warnings" = "Предупреждения";
+"admin_settings_tuning_showReason" = "Показывать причину";
+"admin_settings_tuning_maintenanceMode" = "Технические работы";
+"admin_settings_tuning_all" = "Все";
+"admin_settings_tuning_messenger" = "Мессенджер";
+"admin_settings_tuning_user" = "Пользователь";
+"admin_settings_tuning_group" = "Сообщества";
+"admin_settings_tuning_comment" = "Комментарии";
+"admin_settings_tuning_gifts" = "Подарки";
+"admin_settings_tuning_notes" = "Заметки";
+"admin_settings_tuning_notification" = "Уведомления";
+"admin_settings_tuning_topics" = "Обсуждения";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_enabled" = "Включено";
+"admin_settings_tuning_menu" = "Меню";
+"admin_settings_tuning_links" = "Ссылки";
+"admin_settings_tuning_about" = "О сайте";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_adPoster" = "Рекламный баннер";
+"admin_settings_tuning_src" = "Источник";
+"admin_settings_tuning_caption" = "Подпись";
+"admin_settings_tuning_link" = "Ссылка";
+"admin_settings_tuning_defaultMobileTheme" = "Тема для мобильных устройств по умолчанию";
+"admin_settings_tuning_telemetry" = "Телеметрия";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_container" = "Контейнер";
+"admin_settings_tuning_site" = "Сайт";
+"admin_settings_tuning_credentials" = "Данные";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_client" = "Клиент";
+"admin_settings_tuning_layer" = "Слой";
+"admin_settings_tuning_secret" = "Секретный ключ";
+"admin_settings_tuning_token" = "Токен";
+"admin_settings_tuning_helpdeskChat" = "Чат Helpdesk";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_database" = "База данных";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_password" = "Пароль";
+"admin_settings_tuning_notificationsBroker" = "Брокер уведомлений";
+"admin_settings_tuning_domain" = "Домен";
+"admin_settings_tuning_server" = "Сервер";
+"admin_settings_tuning_address" = "Адрес";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
+"admin_settings_tuning_hint" = "Подсказка";
+"admin_settings_tuning_addr" = "Адрес";
+"admin_settings_tuning_port" = "Порт";
+"admin_settings_tuning_topic" = "Тема";
diff --git a/locales/ru_old.strings b/locales/ru_old.strings
index d0917f65..7b242eae 100644
--- a/locales/ru_old.strings
+++ b/locales/ru_old.strings
@@ -773,4 +773,18 @@
"reset" = "Сбросъ";
"closed_group_post" = "Это высказыванiе изъ закрытого общѣства";
-"deleted_target_comment" = "Этотъ отзыв принадлѣжит к удалѣнному высказыванiю";
\ No newline at end of file
+"deleted_target_comment" = "Этотъ отзыв принадлѣжит к удалѣнному высказыванiю";
+
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
diff --git a/locales/ru_sov.strings b/locales/ru_sov.strings
index 903910a1..4464edc8 100644
--- a/locales/ru_sov.strings
+++ b/locales/ru_sov.strings
@@ -978,4 +978,18 @@
"reset" = "Сброс";
"closed_group_post" = "Эта запись из закрытого собрания";
-"deleted_target_comment" = "Этот отзыв надлежит к удалённой записи";
\ No newline at end of file
+"deleted_target_comment" = "Этот отзыв надлежит к удалённой записи";
+
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
diff --git a/locales/sr_cyr.strings b/locales/sr_cyr.strings
index 2ce12e27..2cf980ed 100644
--- a/locales/sr_cyr.strings
+++ b/locales/sr_cyr.strings
@@ -470,3 +470,16 @@
"paginator_back" = "Враћати се";
"paginator_page" = "Страница бр. $1";
"paginator_next" = "Следећа страница";
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
diff --git a/locales/sr_lat.strings b/locales/sr_lat.strings
index 0f382499..171b54de 100644
--- a/locales/sr_lat.strings
+++ b/locales/sr_lat.strings
@@ -471,3 +471,16 @@
"paginator_back" = "Vraćati se";
"paginator_page" = "Stranica br. $1";
"paginator_next" = "Sledeća stranica";
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
diff --git a/locales/tr.strings b/locales/tr.strings
index 8184a5df..ff023ce4 100644
--- a/locales/tr.strings
+++ b/locales/tr.strings
@@ -550,3 +550,16 @@
"paginator_next" = "İleri";
/* Translated by @WindowZ414 - @WindowZ414 tarafından çevirildi */
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
diff --git a/locales/udm.strings b/locales/udm.strings
index 497a4cc6..66641e88 100644
--- a/locales/udm.strings
+++ b/locales/udm.strings
@@ -809,3 +809,16 @@
/* User alerts */
"user_alert_scam" = "мошенничество тросгес герӟаськемын та to вылэ ӝожтӥсько. Пожалуйста, сак луыны, уката ик дорын тонэ уксё куре ке.";
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";
diff --git a/locales/uk.strings b/locales/uk.strings
index 7ccfb367..e0da5cff 100644
--- a/locales/uk.strings
+++ b/locales/uk.strings
@@ -1438,3 +1438,16 @@
"mobile_like" = "Подобається";
"mobile_user_info_hide" = "Приховувати";
"mobile_user_info_show_details" = "Показати докладніше";
+"admin_settings_tuning_openvk" = "OpenVK";
+"admin_settings_tuning_api" = "API";
+"admin_settings_tuning_ton" = "TON";
+"admin_settings_tuning_url" = "URL";
+"admin_settings_tuning_piwik" = "Piwik";
+"admin_settings_tuning_matomo" = "Matomo";
+"admin_settings_tuning_smsc" = "SMSC";
+"admin_settings_tuning_telegram" = "Telegram";
+"admin_settings_tuning_eventDB" = "eventDB";
+"admin_settings_tuning_kafka" = "Kafka";
+"admin_settings_tuning_dsn" = "DSN";
+"admin_settings_tuning_testnet" = "Testnet";
+"admin_settings_tuning_regex" = "Regex";