diff --git a/Web/Presenters/AdminPresenter.php b/Web/Presenters/AdminPresenter.php index ff21612b2..6ce81d6ea 100644 --- a/Web/Presenters/AdminPresenter.php +++ b/Web/Presenters/AdminPresenter.php @@ -550,4 +550,227 @@ function renderChandlerUser(string $UUID): void $this->redirect("/admin/users/id" . $user->getId()); } + + function renderTranslation(): void + { + $lang = $this->queryParam("lang") ?? "ru"; + $q = $this->queryParam("q"); + $lines = []; + $new_key = true; + + if ($lang === "any" || $this->queryParam("langs")) { + if (!$q || trim($q) === "") { + $this->flashFail("err", tr("translation_enter_query_first")); + return; + } + + $locales = $this->queryParam("langs") ? explode(",", $this->queryParam("langs")) : array_filter(scandir(__DIR__ . "/../../locales/"), function ($file) { + return preg_match('/\.strings$/', $file); + }); + + $_locales = []; + foreach ($locales as $locale) + $_locales[] = explode(".", $locale)[0]; + + foreach ($locales as $locale) { + $handle = fopen(__DIR__ . "/../../locales/$locale" . ($this->queryParam("langs") ? ".strings" : ''), "r"); + if ($handle) { + $i = 0; + while (($line = fgets($handle)) !== false) { + $i++; + if (preg_match('/"(.*)" = "(.*)"(;)?/', $line, $matches)) { + $val = ["index" => $i, "key" => $matches[1], "lang" => explode(".", $locale)[0], "value" => $matches[2]]; + if (!in_array($val["key"], ["__locale", "__WinEncoding", "__transNames"])) { + if ($q) { + if (str_contains($q, "key:")) { + continue; + } else if (str_contains($q, "value:")) { + $_exact_value_match = preg_match('/value:(.*)/', $q, $_value_matches); + if ($_exact_value_match && $_value_matches[1] !== $val["value"]) { + continue; + } + } else { + if (!str_contains(mb_strtolower($line), mb_strtolower($q))) { + continue; + } + } + } + $lines[] = $val; + } + } + } + fclose($handle); + $new_key = false; + } else { + $this->flash("err", tr("translation_locale_file_not_found")); + } + } + + if (str_contains($q, "key:")) { + $_exact_key_match = preg_match('/key:(.*)/', $q, $_key_matches); + if ($_exact_key_match && $_key_matches[1]) { + $i = 0; + $used_langs = []; + foreach ($_locales as $locale) { + if ($i === sizeof($_locales)) break; + $handle = fopen(__DIR__ . "/../../locales/$locale.strings", "r"); + $value = ""; + if ($handle) { + while (($line = fgets($handle)) !== false) { + if (preg_match('/"(' . $_key_matches[1] . ')" = "(.*)"(;)?/', $line, $matches)) { + $value = $matches[2]; + } + $new_key = isset($value); + + } + fclose($handle); + } + + if (!in_array($locale, $used_langs)) { + $lines[] = ["index" => $i, "key" => $_key_matches[1], "lang" => $locale, "value" => $value]; + } + $used_langs[] = $locale; + $i++; + } + } + } + } else { + $new_key = false; + $handle = fopen(__DIR__ . "/../../locales/$lang.strings", "r"); + if ($handle) { + $i = 0; + while (($line = fgets($handle)) !== false) { + $i++; + if (preg_match('/"(.*)" = "(.*)"(;)?/', $line, $matches)) { + $val = ["index" => $i, "key" => $matches[1], "lang" => $lang, "value" => $matches[2]]; + if (!in_array($val["key"], ["__locale", "__WinEncoding", "__transNames"])) { + if ($q) { + if (str_contains($q, "key:")) { + $_exact_key_match = preg_match('/key:(.*)/', $q, $_key_matches); + if ($_exact_key_match && $_key_matches[1] !== $val["key"]) { + continue; + } + } else if (str_contains($q, "value:")) { + $_exact_value_match = preg_match('/value:(.*)/', $q, $_value_matches); + if ($_exact_value_match && $_value_matches[1] !== $val["value"]) { + continue; + } + } else { + if (!str_contains(mb_strtolower($line), mb_strtolower($q))) { + continue; + } + } + } + $lines[] = $val; + } + } + } + fclose($handle); + } else { + $this->flash("err", tr("translation_locale_file_not_found")); + } + } + + $this->template->languages = getLanguages(); + $this->template->activeLang = $lang; + $this->template->keys = $lines; + $this->template->q = str_replace('"', '', $q); + $this->template->scrollTo = $this->queryParam("s"); + $this->template->langs = $this->queryParam("langs"); + $this->template->new_key = $new_key; + } + + function renderTranslateKey(): void + { + if ($_SERVER["REQUEST_METHOD"] === "POST") { + $this->assertNoCSRF(); + + if (empty($this->postParam("strings"))) { + $lang = $this->postParam("lang"); + $key = $this->postParam("key"); + $value = addslashes($this->postParam("value")); + + $handle = fopen(__DIR__ . "/../../locales/$lang.strings", "c"); + if ($handle) { + if ($this->postParam("act") !== "delete") { + $file = file_get_contents(__DIR__ . "/../../locales/$lang.strings"); + if ($file) { + $handle = fopen(__DIR__ . "/../../locales/$lang.strings", "c"); + if (preg_match('/"(' . $key . ')" = "(.*)";/', $file)) { + $replacement = rtrim(preg_replace('/"(' . $key . ')" = "(.*)";/', '"$1" = "' . $value . '";', $file), ""); + + if (file_put_contents(__DIR__ . "/../../locales/$lang.strings", $replacement)) { + fclose($handle); + $this->returnJson(["success" => true]); + } else { + fclose($handle); + $this->returnJson(["success" => false, "error" => tr("translation_file_writing_error")]); + } + } else { + $file .= "\"$key\" = \"$value\";\n"; + if (fwrite($handle, $file)) { + fclose($handle); + $this->returnJson(["success" => true]); + } else { + fclose($handle); + $this->returnJson(["success" => false, "error" => tr("translation_file_writing_error")]); + } + } + } else { + $this->returnJson(["success" => false, "error" => tr("translation_locale_file_not_found")]); + } + } else { + $file = file(__DIR__ . "/../../locales/$lang.strings"); + $new_file = []; + foreach ($file as &$line) { + if (!preg_match('/"(' . $key . ')" = "(' . $value . ')";/', $line)) { + $new_file[] = $line; + } + } + file_put_contents(__DIR__ . "/../../locales/$lang.strings", implode("", $new_file)); + fclose($handle); + $this->returnJson(["success" => true]); + } + } else { + $this->returnJson(["success" => false, "error" => tr("translation_file_reading_error")]); + } + } else { + $objects = explode(";", $this->postParam("strings")); + if (sizeof($objects) < 2) { + $this->returnJson(["success" => false, "error" => tr("translation_enter_at_least_two_values")]); + } + + $succ = 0; + foreach ($objects as $object) { + $data = explode(":", $object); + $lang = $data[0]; + $key = $data[1]; + $value = addslashes($data[2]); + + $file = file_get_contents(__DIR__ . "/../../locales/$lang.strings"); + if ($file) { + $handle = fopen(__DIR__ . "/../../locales/$lang.strings", "c"); + if ($handle) { + if (preg_match('/"(' . $key . ')" = "(.*)";/', $file)) { + $replacement = preg_replace('/"(' . $key . ')" = "(.*)";/', '"$1" = "' . $value . '";', $file); + if (file_put_contents(__DIR__ . "/../../locales/$lang.strings", $replacement)) { + $succ++; + } + } else { + $file .= "\"$key\" = \"$value\";\n"; + if (fwrite($handle, $file)) { + $succ++; + } + } + fclose($handle); + } + } + } + + $this->returnJson(["success" => true, "count" => $succ]); + } + } else { + $this->notFound(); + } + } } diff --git a/Web/Presenters/templates/@layout.xml b/Web/Presenters/templates/@layout.xml index 1718c4990..a0958cba5 100644 --- a/Web/Presenters/templates/@layout.xml +++ b/Web/Presenters/templates/@layout.xml @@ -204,6 +204,7 @@ {var $menuLinksAvaiable = sizeof(OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links']) > 0 && $thisUser->getLeftMenuItemStatus('links')}
{_admin} + {_translations} {_helpdesk} {if $helpdeskTicketNotAnsweredCount > 0} ({$helpdeskTicketNotAnsweredCount}) diff --git a/Web/Presenters/templates/Admin/@layout.xml b/Web/Presenters/templates/Admin/@layout.xml index 7b1a30f3a..9f1951bfd 100644 --- a/Web/Presenters/templates/Admin/@layout.xml +++ b/Web/Presenters/templates/Admin/@layout.xml @@ -124,6 +124,9 @@