From 24d25011870f8fdf0827e410a0ea667bf80b3495 Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Mon, 21 Jul 2025 19:14:51 -0400 Subject: [PATCH] feat: Russian localization for Anubis (#882) * feat(localization): Add Russian language translation * test(localization): ensure Russian translations are tested Signed-off-by: Xe Iaso * docs(changelog): update with Russian translation Signed-off-by: Xe Iaso --------- Signed-off-by: Xe Iaso Signed-off-by: Xe Iaso Co-authored-by: MichaelAgarkov --- docs/docs/CHANGELOG.md | 1 + lib/localization/locales/manifest.json | 1 + lib/localization/locales/ru.json | 64 ++++++++++++++++++++++++++ lib/localization/localization_test.go | 8 +++- 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 lib/localization/locales/ru.json diff --git a/docs/docs/CHANGELOG.md b/docs/docs/CHANGELOG.md index 145efa1..b159a1b 100644 --- a/docs/docs/CHANGELOG.md +++ b/docs/docs/CHANGELOG.md @@ -22,6 +22,7 @@ Anubis now supports these new languages: - [Czech](https://github.com/TecharoHQ/anubis/pull/849) - [Finnish](https://github.com/TecharoHQ/anubis/pull/863) +- [Russian](https://github.com/TecharoHQ/anubis/pull/882) Anubis now supports the [`missingHeader`](./admin/configuration/expressions.mdx#missingHeader) to assert the absence of headers in requests. diff --git a/lib/localization/locales/manifest.json b/lib/localization/locales/manifest.json index 014592e..cf80a2e 100644 --- a/lib/localization/locales/manifest.json +++ b/lib/localization/locales/manifest.json @@ -12,6 +12,7 @@ "it", "ja", "pt-BR", + "ru", "tr", "zh-CN", "zh-TW" diff --git a/lib/localization/locales/ru.json b/lib/localization/locales/ru.json new file mode 100644 index 0000000..629fe97 --- /dev/null +++ b/lib/localization/locales/ru.json @@ -0,0 +1,64 @@ +{ + "loading": "Загрузка...", + "why_am_i_seeing": "Почему я вижу это?", + "protected_by": "Защищено", + "protected_from": "От", + "made_with": "Сделано с ❤️ из 🇨🇦", + "mascot_design": "Дизайн маскота от", + "ai_companies_explanation": "Вы это видите, потому что администратор этого сайта настроил Anubis для защиты сервера от атак, использующих ИИ, которые агрессивно копируют данные с сайтов. Это может привести к зависанию сайтов и делает их ресурсы недоступными для всех.", + "anubis_compromise": "Anubis - это компромисс. Anubis использует Proof-of-Work, похожую на Hashcash, для борьбы со спамом в электронной почте. Идея в том, что на отдельных уровнях дополнительная нагрузка не влиятельна, но на уровне массового парсинга она накапливается и значительно удорожает сбор данных.", + "hack_purpose": "В реальности, это хак, у которого настоящая цель - предоставить «достаточно хорошее» решение, чтобы можно было потратить больше времени на идентификацию headless-браузеров (например, по тому, как они выполняют отрисовку шрифтов), чтобы не отображать страницу с подтверждением пользователям, которые с гораздо большей вероятностью являются настоящими.", + "jshelter_note": "Anubis требует использования современных функций JavaScript, которые плагины, по типу JShelter, отключают. Пожалуйста, отключите JShelter и другие подобные плагины для этого домена.", + "version_info": "На сайте запущен Anubis версии", + "try_again": "Попробуйте снова", + "go_home": "Перейти на домашнюю", + "contact_webmaster": "если вы уверены, что это ошибка, свяжитесь с владельцем сайта через", + "connection_security": "Пожалуйста, подождите, пока мы проверим безопасность вашего соединения.", + "javascript_required": "К сожалению, для решения этой проверки необходимо включить JavaScript. Это необходимо, поскольку компании, занимающиеся разработкой ИИ, изменили моральные правила, касающийся хостинга веб-сайтов. Решение без использования JavaScript находится в стадии разработки.", + "benchmark_requires_js": "Для работы тестирования необходимо включить JavaScript.", + "difficulty": "Сложность:", + "algorithm": "Алгоритм:", + "compare": "Сравнить:", + "time": "Время", + "iters": "Итерации", + "time_a": "Время A", + "iters_a": "Итерации A", + "time_b": "Время B", + "iters_b": "Итерации B", + "static_check_endpoint": "Это всего лишь точка проверки, которую может использовать ваш обратный прокси-сервер.", + "authorization_required": "Требуется авторизация.", + "cookies_disabled": "В вашем браузере отключены cookie файлы. Anubis требует их для подтверждения того, что вы являетесь настоящим человеком. Пожалуйста, включите файлы cookie для этого домена", + "access_denied": "Доступ запрещён: код ошибки", + "dronebl_entry": "DroneBL сообщил о записи", + "see_dronebl_lookup": "см.", + "internal_server_error": "Внутренняя ошибка сервера: администратор неправильно настроил Anubis. Обратитесь к администратору и попросите его просмотреть логи", + "invalid_redirect": "Неверное перенаправление", + "redirect_not_parseable": "URL-адрес перенаправления не может быть анализирован", + "redirect_domain_not_allowed": "Перенаправление домена запрещено", + "failed_to_sign_jwt": "не смог подписать JWT", + "invalid_invocation": "Неверный вызов MakeChallenge", + "client_error_browser": "Ошибка клиента: убедитесь, что у вас браузер новейшей версии, и повторите попытку позже.", + "oh_noes": "О нет!", + "benchmarking_anubis": "Анализ Анубиса!", + "you_are_not_a_bot": "Вы не бот!", + "making_sure_not_bot": "Проверяем, что вы не бот!", + "celphase": "CELPHASE", + "js_web_crypto_error": "В вашем браузере отсутствует функция web.crypto. Вы просматриваете страницу через защищённый контекст?", + "js_web_workers_error": "Ваш браузер не поддерживает web worker (Anubis использует его, чтобы избежать зависания браузера). У вас установлен плагин типа JShelter?", + "js_cookies_error": "Ваш браузер не сохраняет cookie файлы. Anubis использует их для определения клиентов, прошедших проверку, сохраняя подписанный токен в файле cookie. Включите сохранение файлов cookie для этого домена. Имена файлов cookie, хранимых Anubis, могут изменяться без предварительного уведомления. Имена и значения cookie файлов не являются частью общедоступного API.", + "js_context_not_secure": "Ваш контекст небезопасен!", + "js_context_not_secure_msg": "Попробуйте подключиться по HTTPS или попросите администратора, чтобы он настроил HTTPS. Подробнее см. MDN.", + "js_calculating": "Расчёт...", + "js_missing_feature": "Отсутствует функция", + "js_challenge_error": "Ошибка проверки!", + "js_challenge_error_msg": "Не удалось определить алгоритм проверки. Возможно, нужно перезагрузить страницу..", + "js_calculating_difficulty": "Расчёт...
Сложность:", + "js_speed": "Скорость:", + "js_verification_longer": "Проверка занимает больше времени, чем ожидалось. Пожалуйста, не обновляйте страницу.", + "js_success": "Успех!", + "js_done_took": "Получилось! Заняло", + "js_iterations": "итераций", + "js_finished_reading": "Я дочитал, продолжить →", + "js_calculation_error": "Ошибка расчёта!", + "js_calculation_error_msg": "Не удалось рассчитать задачу:" +} \ No newline at end of file diff --git a/lib/localization/localization_test.go b/lib/localization/localization_test.go index 5e7abf0..b8e1b83 100644 --- a/lib/localization/localization_test.go +++ b/lib/localization/localization_test.go @@ -23,6 +23,7 @@ func TestLocalizationService(t *testing.T) { "is": "Hleður...", "pt-BR": "Carregando...", "tr": "Yükleniyor...", + "ru": "Загрузка...", "zh-CN": "加载中...", "zh-TW": "載入中...", } @@ -57,7 +58,7 @@ func TestLocalizationService(t *testing.T) { } type manifest struct { - SupportedLanguages []string `json:"supported_languages"` + SupportedLanguages []string `json:"supportedLanguages"` } func loadManifest(t *testing.T) manifest { @@ -98,6 +99,11 @@ func TestComprehensiveTranslations(t *testing.T) { sort.Strings(keys) + manifest := loadManifest(t) + if len(manifest.SupportedLanguages) == 0 { + t.Fatal("no languages loaded") + } + for _, lang := range loadManifest(t).SupportedLanguages { t.Run(lang, func(t *testing.T) { loc := service.GetLocalizer(lang)