mod: update Russian to English translations in templates and forms for improved accessibility
HYPN0 Build and Push Docker Image / build-and-push (push) Successful in 31s
HYPN0 Build and Push Docker Image / build-and-push (push) Successful in 31s
This commit is contained in:
+14
-14
@@ -6,25 +6,25 @@ class HalftoneGenerateForm(forms.Form):
|
||||
Форма валидации входных параметров для генерации гипнотического SVG.
|
||||
"""
|
||||
SHAPE_CHOICES = [
|
||||
("circle", "Круг"),
|
||||
("ring", "Кольцо"),
|
||||
("triangle", "Треугольник"),
|
||||
("square", "Квадрат"),
|
||||
("diamond", "Ромб"),
|
||||
("hexagon", "Шестиугольник"),
|
||||
("star", "Звезда"),
|
||||
("cross", "Крестик"),
|
||||
("line", "Линия"),
|
||||
("snowflake", "Снежинка"),
|
||||
("binary", "Матрица (0/1)"),
|
||||
("heart", "Сердечко"),
|
||||
("circle", "Circle"),
|
||||
("ring", "Ring"),
|
||||
("triangle", "Triangle"),
|
||||
("square", "Square"),
|
||||
("diamond", "Diamond"),
|
||||
("hexagon", "Hexagon"),
|
||||
("star", "Star"),
|
||||
("cross", "Cross"),
|
||||
("line", "Line"),
|
||||
("snowflake", "Snowflake"),
|
||||
("binary", "Binary (0/1)"),
|
||||
("heart", "Heart"),
|
||||
]
|
||||
|
||||
image = forms.ImageField(
|
||||
required=True,
|
||||
error_messages={
|
||||
"required": "Покорми Гипножабу изображением!",
|
||||
"invalid_image": "Гипножаба не может переварить этот файл. Нужна картинка (PNG, JPG, WEBP).",
|
||||
"required": "Feed the Hypnotoad with an image!",
|
||||
"invalid_image": "Hypnotoad cannot digest this file. Image required (PNG, JPG, WEBP).",
|
||||
},
|
||||
)
|
||||
shape = forms.ChoiceField(
|
||||
|
||||
@@ -596,13 +596,13 @@ class TbBlogPost(models.Model):
|
||||
def blog_nav_title(self) -> str:
|
||||
"""Детерминированный выбор названия раздела блога для навигации на основе ID статьи."""
|
||||
nav_titles = (
|
||||
"Блог Мозгоклюя",
|
||||
"Записки Гипножабы",
|
||||
"Дневник Мозговых Перцепторов",
|
||||
"Хроники психо-резонанса",
|
||||
"Мемуары астрального архива",
|
||||
"Манифесты волновой матрицы",
|
||||
"Бортовой журнал транс-погружения",
|
||||
"Brain Slug Blog",
|
||||
"Hypnotoad Field Notes",
|
||||
"Neural Perceptor Diary",
|
||||
"Psycho-Resonance Chronicles",
|
||||
"Astral Archive Memoirs",
|
||||
"Wave Matrix Manifestos",
|
||||
"Deep Trance Flight Log",
|
||||
)
|
||||
if not self.id:
|
||||
return nav_titles[0]
|
||||
|
||||
@@ -47,7 +47,7 @@ HYPNO_GENITIVES = [
|
||||
HYPNO_POSTFIXES = [
|
||||
"#42", "v3.14", "(Ultra)", "(Phase 7)", "(Alpha)", "(Omega)", "(Protocol 09)", "(Revision 14)",
|
||||
"(Extract)", "(Layer 9)", "(Ward 106)", "(Hangar 18)", "(Unfinished Opus)", "(Secret Project)",
|
||||
"[Classified]", "(DOOP-66)", "(Sub-Level 4)", "(MK-Ultra)", "С90"
|
||||
"[Classified]", "(DOOP-66)", "(Sub-Level 4)", "(MK-Ultra)", "C90"
|
||||
]
|
||||
|
||||
|
||||
|
||||
+65
-65
@@ -232,7 +232,7 @@ class HalftoneViewTests(BaseMediaTestCase):
|
||||
self.assertContains(response, 'X-CSRFToken')
|
||||
self.assertContains(response, "handleFileChange")
|
||||
self.assertContains(response, "imagePreviewUrl")
|
||||
self.assertContains(response, "Гипножаба облизывается на:")
|
||||
self.assertContains(response, "Hypnotoad salivates over:")
|
||||
# Проверяем, что csrf_token не пустой в hx-headers
|
||||
content = response.content.decode("utf-8")
|
||||
self.assertNotIn('hx-headers=\'{"X-CSRFToken": ""}\'', content)
|
||||
@@ -291,7 +291,7 @@ class HalftoneViewTests(BaseMediaTestCase):
|
||||
def test_generate_post_no_image(self):
|
||||
response = self.client.post(reverse("hypn0_site:generate"), data={"shape": "circle"})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Покорми Гипножабу")
|
||||
self.assertContains(response, "Feed the Hypnotoad")
|
||||
|
||||
def test_generate_post_success(self):
|
||||
buf = io.BytesIO()
|
||||
@@ -366,8 +366,8 @@ class PublishViewTests(BaseMediaTestCase):
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Мозговые слизняки протестуют!")
|
||||
self.assertContains(response, "Подчиниться и опубликовать")
|
||||
self.assertContains(response, "Brain Slugs are rioting!")
|
||||
self.assertContains(response, "Submit and Publish")
|
||||
self.assertEqual(TbHypn0Item.objects.count(), 0)
|
||||
|
||||
def test_publish_with_cookie_success(self):
|
||||
@@ -389,8 +389,8 @@ class PublishViewTests(BaseMediaTestCase):
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Уже в галерее транса")
|
||||
self.assertContains(response, "идет прорастание психо-паутины...")
|
||||
self.assertContains(response, "In the Trance Gallery")
|
||||
self.assertContains(response, "psychic neural web expanding…")
|
||||
|
||||
# Проверяем запись в БД
|
||||
self.assertEqual(TbHypn0Item.objects.count(), 1)
|
||||
@@ -419,7 +419,7 @@ class PublishViewTests(BaseMediaTestCase):
|
||||
data={"svg_content": ""},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Нет данных SVG для публикации")
|
||||
self.assertContains(response, "No SVG data for publication")
|
||||
self.assertEqual(TbHypn0Item.objects.count(), 0)
|
||||
|
||||
|
||||
@@ -522,11 +522,11 @@ class GalleryDetailAndDownloadTests(BaseMediaTestCase):
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Астральный Транс Сознания #42")
|
||||
self.assertContains(response, f"#{self.item.s_hash_id}")
|
||||
self.assertContains(response, "Векторная анатомия")
|
||||
self.assertContains(response, "Синтез психо-сетки")
|
||||
self.assertContains(response, "Астральный паспорт")
|
||||
self.assertContains(response, "Копировать SVG-код")
|
||||
self.assertContains(response, "Скачать .svg")
|
||||
self.assertContains(response, "Vector Anatomy")
|
||||
self.assertContains(response, "Psych-Grid Synthesis")
|
||||
self.assertContains(response, "Astral Passport")
|
||||
self.assertContains(response, "Copy SVG code")
|
||||
self.assertContains(response, "Download .svg")
|
||||
|
||||
# Проверка инкремента просмотров
|
||||
self.item.refresh_from_db()
|
||||
@@ -557,7 +557,7 @@ class GalleryDetailAndDownloadTests(BaseMediaTestCase):
|
||||
client = Client()
|
||||
response = client.post(reverse("hypn0_site:gallery_vote", kwargs={"hash_id": self.item.s_hash_id}))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Подчинитесь воле Гипножабы!")
|
||||
self.assertContains(response, "Surrender to Hypnotoad!")
|
||||
|
||||
|
||||
class GalleryRandomAndNavigationTests(BaseMediaTestCase):
|
||||
@@ -699,8 +699,8 @@ class UnconsciousMatrixTests(BaseMediaTestCase):
|
||||
item = self.items[0]
|
||||
response = self.client.get(reverse("hypn0_site:gallery_detail", kwargs={"hash_id": item.s_hash_id}))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Матрица бессознательного")
|
||||
self.assertContains(response, "5 узлов")
|
||||
self.assertContains(response, "Matrix of the Unconscious")
|
||||
self.assertContains(response, "5 nodes")
|
||||
self.assertContains(response, f"#{item.s_hash_id}")
|
||||
self.assertContains(response, "btn-nav-prev")
|
||||
self.assertContains(response, "btn-nav-next")
|
||||
@@ -782,7 +782,7 @@ class GalleryFreshFloorTests(BaseMediaTestCase):
|
||||
|
||||
response = self.client.get(reverse("hypn0_site:index"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Плеск бессознательного")
|
||||
self.assertContains(response, "Incubator of the Unconscious")
|
||||
self.assertContains(response, "FRESH STREAM")
|
||||
self.assertContains(response, f"gallery-card-{item.s_hash_id}")
|
||||
self.assertContains(response, f"¤{item.s_hash_id}")
|
||||
@@ -935,12 +935,12 @@ class GalleryArchiveTests(BaseMediaTestCase):
|
||||
url = reverse("hypn0_site:gallery_archive")
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Галерея транса")
|
||||
self.assertContains(response, "Trance Gallery")
|
||||
self.assertContains(response, "ARCHIVE")
|
||||
self.assertContains(response, "Все волны")
|
||||
self.assertContains(response, "Инкубатор")
|
||||
self.assertContains(response, "Одобрено")
|
||||
self.assertContains(response, "Золотой фонд")
|
||||
self.assertContains(response, "All waves")
|
||||
self.assertContains(response, "Incubator")
|
||||
self.assertContains(response, "Approved")
|
||||
self.assertContains(response, "Hall of Fame")
|
||||
# Все 3 картины присутствуют в выдаче
|
||||
self.assertContains(response, f"gallery-card-{self.item_fresh.s_hash_id}")
|
||||
self.assertContains(response, f"gallery-card-{self.item_curated.s_hash_id}")
|
||||
@@ -1013,21 +1013,21 @@ class GalleryArchiveTests(BaseMediaTestCase):
|
||||
resp_p1 = self.client.get(url, data={"floor": "all", "sort": "likes"})
|
||||
self.assertEqual(resp_p1.status_code, 200)
|
||||
self.assertEqual(len(resp_p1.context["page_obj"]), 16)
|
||||
self.assertContains(resp_p1, "Фаза 1 из 2")
|
||||
self.assertContains(resp_p1, "<title>Галерея транса — Каталог анимированных картин | HypnoSVG</title>")
|
||||
self.assertContains(resp_p1, "Phase 1 of 2")
|
||||
self.assertContains(resp_p1, "<title>Trance Gallery — Animated SVG Catalog | HypnoSVG</title>")
|
||||
# Проверяем сохранение query-параметров в ссылках пагинатора
|
||||
self.assertContains(resp_p1, "floor=all&sort=likes&page=2")
|
||||
|
||||
resp_p2 = self.client.get(url, data={"floor": "all", "sort": "likes", "page": 2})
|
||||
self.assertEqual(resp_p2.status_code, 200)
|
||||
self.assertEqual(len(resp_p2.context["page_obj"]), 2)
|
||||
self.assertContains(resp_p2, "Фаза 2 из 2")
|
||||
self.assertContains(resp_p2, "<title>Галерея транса — Каталог анимированных картин (Фаза 2) | HypnoSVG</title>")
|
||||
self.assertContains(resp_p2, "Phase 2 of 2")
|
||||
self.assertContains(resp_p2, "<title>Trance Gallery — Animated SVG Catalog (Phase 2) | HypnoSVG</title>")
|
||||
self.assertContains(resp_p2, "floor=all&sort=likes&page=1")
|
||||
|
||||
# Проверяем Title при фильтрации по этажу
|
||||
resp_curated = self.client.get(url, data={"floor": "curated"})
|
||||
self.assertContains(resp_curated, "<title>Одобрено Мозговым Слизнем | HypnoSVG</title>")
|
||||
self.assertContains(resp_curated, "<title>Approved by Brain Slug | HypnoSVG</title>")
|
||||
|
||||
|
||||
class RescoreCommandTests(BaseMediaTestCase):
|
||||
@@ -1311,12 +1311,12 @@ class BlogPostModelAndAdminTests(BaseMediaTestCase):
|
||||
# Проверяем, что отображается один из динамических заголовков секции
|
||||
content = response.content.decode("utf-8")
|
||||
possible_headings = (
|
||||
"Сигналы из параллельного континуума",
|
||||
"Психо-артефакты ноосферы",
|
||||
"Заметки астрального консилиума",
|
||||
"Рефлекторные отклики мозговых слизней",
|
||||
"Публикации из глубин подсознания",
|
||||
"Материалы хроник гипноза",
|
||||
"Signals from Parallel Continuum",
|
||||
"Noosphere Psycho-Artifacts",
|
||||
"Astral Council Field Notes",
|
||||
"Reflexive Responses of Brain Slugs",
|
||||
"Dispatches from Subconscious Depths",
|
||||
"Materials from Hypno Chronicles",
|
||||
)
|
||||
self.assertTrue(any(heading in content for heading in possible_headings))
|
||||
self.assertContains(response, "Хроники гипно-транса: Урок 1")
|
||||
@@ -1345,7 +1345,7 @@ class BlogPostModelAndAdminTests(BaseMediaTestCase):
|
||||
# Проверка 1-й страницы ленты блога
|
||||
response = self.client.get("/blog")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Хроники гипноза")
|
||||
self.assertContains(response, "Hypno Chronicles")
|
||||
self.assertContains(response, "Тестовая депеша 11")
|
||||
self.assertNotContains(response, "Черновик ноосферы")
|
||||
self.assertContains(response, "page=2")
|
||||
@@ -1388,7 +1388,7 @@ class BlogPostModelAndAdminTests(BaseMediaTestCase):
|
||||
resp_parent = self.client.get(f"/blog/{series_parent.slug}")
|
||||
self.assertEqual(resp_parent.status_code, 200)
|
||||
self.assertContains(resp_parent, "Цикл: Основы векторного гипноза")
|
||||
self.assertContains(resp_parent, "Материалы и главы этого цикла")
|
||||
self.assertContains(resp_parent, "Chapters in This Series")
|
||||
self.assertContains(resp_parent, "Глава 1: Первичная модуляция")
|
||||
self.assertContains(resp_parent, "Глава 2: Фазовый сдвиг матрицы")
|
||||
|
||||
@@ -1396,31 +1396,31 @@ class BlogPostModelAndAdminTests(BaseMediaTestCase):
|
||||
resp_ch1 = self.client.get(f"/blog/{ch1.slug}")
|
||||
self.assertEqual(resp_ch1.status_code, 200)
|
||||
self.assertContains(resp_ch1, "Глава 1: Первичная модуляция")
|
||||
self.assertContains(resp_ch1, "Материал входит в серию:")
|
||||
self.assertContains(resp_ch1, "Part of the series:")
|
||||
self.assertContains(resp_ch1, self.item.s_title)
|
||||
self.assertContains(resp_ch1, f"#{self.item.s_hash_id}")
|
||||
self.assertContains(resp_ch1, f"/gallery/{self.item.s_hash_id}")
|
||||
self.assertContains(resp_ch1, "Скачать SVG")
|
||||
self.assertContains(resp_ch1, "Вес:")
|
||||
self.assertContains(resp_ch1, "Следующая глава цикла")
|
||||
self.assertContains(resp_ch1, "Download SVG")
|
||||
self.assertContains(resp_ch1, "Weight:")
|
||||
self.assertContains(resp_ch1, "Next chapter in series")
|
||||
self.assertContains(resp_ch1, "Глава 2: Фазовый сдвиг матрицы")
|
||||
|
||||
# Проверка хлебных крошек
|
||||
self.assertContains(resp_ch1, 'aria-label="Хлебные крошки"')
|
||||
self.assertContains(resp_ch1, 'aria-label="Breadcrumbs"')
|
||||
self.assertContains(resp_ch1, ch1.blog_nav_title)
|
||||
self.assertContains(resp_ch1, "Глава 1 из 2")
|
||||
self.assertContains(resp_ch1, "Chapter 1 of 2")
|
||||
self.assertContains(resp_ch1, 'aria-current="page"')
|
||||
|
||||
# Проверка JSON-LD BreadcrumbList
|
||||
self.assertContains(resp_ch1, '"@type": "BreadcrumbList"')
|
||||
self.assertContains(resp_ch1, '"name": "Главная"')
|
||||
self.assertContains(resp_ch1, '"name": "Хроники гипноза"')
|
||||
self.assertContains(resp_ch1, '"name": "Home"')
|
||||
self.assertContains(resp_ch1, '"name": "Hypno Chronicles"')
|
||||
self.assertContains(resp_ch1, series_parent.s_title)
|
||||
|
||||
# 3. Проверка второй главы (ссылка назад на главу 1)
|
||||
resp_ch2 = self.client.get(f"/blog/{ch2.slug}")
|
||||
self.assertEqual(resp_ch2.status_code, 200)
|
||||
self.assertContains(resp_ch2, "Предыдущая глава цикла")
|
||||
self.assertContains(resp_ch2, "Previous chapter in series")
|
||||
self.assertContains(resp_ch2, "Глава 1: Первичная модуляция")
|
||||
|
||||
# 4. Проверка доступа по числовому ID
|
||||
@@ -1437,10 +1437,10 @@ class BlogPostModelAndAdminTests(BaseMediaTestCase):
|
||||
"""Проверка отдачи кастомной страницы 404 в режиме DEBUG=False."""
|
||||
response = self.client.get("/totally-non-existent-hypno-route-404")
|
||||
self.assertEqual(response.status_code, 404)
|
||||
self.assertContains(response, "Гипноузел не обнаружен", status_code=404)
|
||||
self.assertContains(response, "СБОЙ МАТРИЦЫ // КОД? 404", status_code=404)
|
||||
self.assertContains(response, "Hypno-Node Not Found", status_code=404)
|
||||
self.assertContains(response, "MATRIX ANOMALY // CODE 404", status_code=404)
|
||||
self.assertContains(response, "return-btn", status_code=404)
|
||||
self.assertContains(response, "Стираем остатки несущес­твующей страницы", status_code=404)
|
||||
self.assertContains(response, "Erasing traces of the phantom page", status_code=404)
|
||||
|
||||
@override_settings(DEBUG=True)
|
||||
def test_debug_error_preview_routing(self):
|
||||
@@ -1448,23 +1448,23 @@ class BlogPostModelAndAdminTests(BaseMediaTestCase):
|
||||
# 1. Индексный список страниц ошибок
|
||||
resp_list = self.client.get("/_error/")
|
||||
self.assertEqual(resp_list.status_code, 200)
|
||||
self.assertContains(resp_list, "Центр отладки страниц ошибок")
|
||||
self.assertContains(resp_list, "Error Pages Debug Center")
|
||||
self.assertContains(resp_list, "/_error/404")
|
||||
self.assertContains(resp_list, "готов к просмотру")
|
||||
self.assertContains(resp_list, "ready to preview")
|
||||
|
||||
# 2. Проверка каждого кода ошибки
|
||||
expected_checks = [
|
||||
("400", 400, "Сбой ментального протокола"),
|
||||
("401", 401, "Требуется ментальная идентификация"),
|
||||
("403", 403, "Отказано бюрократом 24-го уровня"),
|
||||
("404", 404, "Гипноузел не обнаружен"),
|
||||
("413", 413, "Перегрузка сенсорных каналов"),
|
||||
("429", 429, "Слишком много мыслей в секунду"),
|
||||
("500", 500, "Критический перегрев неокортекса"),
|
||||
("502", 502, "Контейнер потерял сознание"),
|
||||
("503", 503, "Плановый сеанс гипнотерапии"),
|
||||
("504", 504, "Разрыв астральной связи"),
|
||||
("under_reconstruction", 200, "Отдел мозга на реконструкции"),
|
||||
("400", 400, "Perceptual Protocol Mismatch"),
|
||||
("401", 401, "Subconscious Identity Required"),
|
||||
("403", 403, "Cognitive Lockdown Active"),
|
||||
("404", 404, "Hypno-Node Not Found"),
|
||||
("413", 413, "Sensory Channel Saturation"),
|
||||
("429", 429, "Too Many Thoughts per Second"),
|
||||
("500", 500, "Introspection Neural Lock"),
|
||||
("502", 502, "Uplink to Hippocampus Lost"),
|
||||
("503", 503, "Scheduled Hypnotherapy in Progress"),
|
||||
("504", 504, "Astral Synapse Timed Out"),
|
||||
("under_reconstruction", 200, "Brain Sector Under Reconstruction"),
|
||||
]
|
||||
|
||||
for code, expected_status, text_fragment in expected_checks:
|
||||
@@ -1478,12 +1478,12 @@ class BlogPostModelAndAdminTests(BaseMediaTestCase):
|
||||
# 3. Предпросмотр с суффиксом .html
|
||||
resp_404_html = self.client.get("/_error/404.html")
|
||||
self.assertEqual(resp_404_html.status_code, 404)
|
||||
self.assertContains(resp_404_html, "Гипноузел не обнаружен", status_code=404)
|
||||
self.assertContains(resp_404_html, "Hypno-Node Not Found", status_code=404)
|
||||
|
||||
# 4. Несуществующий шаблон ошибки в dev-режиме
|
||||
resp_non_existent = self.client.get("/_error/non-existent-code-999")
|
||||
self.assertEqual(resp_non_existent.status_code, 404)
|
||||
self.assertContains(resp_non_existent, "Шаблон для ошибки 'non-existent-code-999' не найден", status_code=404)
|
||||
self.assertContains(resp_non_existent, "Template for error 'non-existent-code-999' not found", status_code=404)
|
||||
|
||||
def test_custom_django_error_handlers(self):
|
||||
"""Проверка прямого вызова стандартных Django-обработчиков ошибок."""
|
||||
@@ -1495,22 +1495,22 @@ class BlogPostModelAndAdminTests(BaseMediaTestCase):
|
||||
req400 = factory.get("/bad-request")
|
||||
resp400 = error_400(req400)
|
||||
self.assertEqual(resp400.status_code, 400)
|
||||
self.assertIn("Сбой ментального протокола", resp400.content.decode("utf-8"))
|
||||
self.assertIn("Perceptual Protocol Mismatch", resp400.content.decode("utf-8"))
|
||||
|
||||
req403 = factory.get("/forbidden")
|
||||
resp403 = error_403(req403)
|
||||
self.assertEqual(resp403.status_code, 403)
|
||||
self.assertIn("Отказано бюрократом 24-го уровня", resp403.content.decode("utf-8"))
|
||||
self.assertIn("Cognitive Lockdown Active", resp403.content.decode("utf-8"))
|
||||
|
||||
req404 = factory.get("/not-found")
|
||||
resp404 = error_404(req404)
|
||||
self.assertEqual(resp404.status_code, 404)
|
||||
self.assertIn("Гипноузел не обнаружен", resp404.content.decode("utf-8"))
|
||||
self.assertIn("Hypno-Node Not Found", resp404.content.decode("utf-8"))
|
||||
|
||||
req500 = factory.get("/server-error")
|
||||
resp500 = error_500(req500)
|
||||
self.assertEqual(resp500.status_code, 500)
|
||||
self.assertIn("Критический перегрев неокортекса", resp500.content.decode("utf-8"))
|
||||
self.assertIn("Introspection Neural Lock", resp500.content.decode("utf-8"))
|
||||
|
||||
def test_s_title_plain_property(self):
|
||||
"""Проверка очистки HTML-тегов и мнемоник в s_title_plain для моделей TbHypn0Item и TbBlogPost."""
|
||||
|
||||
+10
-10
@@ -196,14 +196,14 @@ def debug_error_preview(request: HttpRequest, code: str = "") -> HttpResponse:
|
||||
break
|
||||
except TemplateDoesNotExist:
|
||||
pass
|
||||
status_mark = "готов к просмотру" if exists else "шаблон не создан"
|
||||
status_mark = "ready to preview" if exists else "template not found"
|
||||
links.append(f"<li><a href='/_error/{c}'><strong>/{c}</strong></a> ({status_mark})</li>")
|
||||
|
||||
html = f"""<!doctype html>
|
||||
<html lang="ru">
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Dev: Предпросмотр страниц ошибок // HypnoSVG</title>
|
||||
<title>Dev: Error Pages Preview // HypnoSVG</title>
|
||||
<style>
|
||||
body {{ font-family: ui-monospace, monospace; background: #09090b; color: #d9f99d; padding: 2rem; line-height: 1.6; }}
|
||||
a {{ color: #a3e635; text-decoration: none; border-bottom: 1px dotted #a3e635; }}
|
||||
@@ -215,8 +215,8 @@ def debug_error_preview(request: HttpRequest, code: str = "") -> HttpResponse:
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<h2>Центр отладки страниц ошибок (DEBUG=True)</h2>
|
||||
<p>Выберите код для инспекции верстки и интерактивных скриптов перекалибровки:</p>
|
||||
<h2>Error Pages Debug Center (DEBUG=True)</h2>
|
||||
<p>Select an error code to inspect layout and recalibration scripts:</p>
|
||||
<ul>
|
||||
{''.join(links)}
|
||||
</ul>
|
||||
@@ -244,7 +244,7 @@ def debug_error_preview(request: HttpRequest, code: str = "") -> HttpResponse:
|
||||
|
||||
if not found_template:
|
||||
return HttpResponse(
|
||||
f"<h1>Шаблон для ошибки '{raw_name}' не найден</h1><p>Проверены: {', '.join(template_candidates)}</p><p><a href='/_error/'>← Вернуться к списку</a></p>",
|
||||
f"<h1>Template for error '{raw_name}' not found</h1><p>Checked: {', '.join(template_candidates)}</p><p><a href='/_error/'>← Back to index</a></p>",
|
||||
status=404,
|
||||
content_type="text/html; charset=utf-8",
|
||||
)
|
||||
@@ -281,7 +281,7 @@ def generate(request: HttpRequest) -> HttpResponse:
|
||||
form = HalftoneGenerateForm(request.POST, request.FILES)
|
||||
|
||||
if not form.is_valid():
|
||||
error_msg = next(iter(form.errors.values()))[0] if form.errors else "Ошибка параметров генерации"
|
||||
error_msg = next(iter(form.errors.values()))[0] if form.errors else "Generation parameter error"
|
||||
return render(request, "block/preview.html", {"error": error_msg})
|
||||
|
||||
image_file = form.cleaned_data["image"]
|
||||
@@ -313,7 +313,7 @@ def generate(request: HttpRequest) -> HttpResponse:
|
||||
return render(
|
||||
request,
|
||||
"block/preview.html",
|
||||
{"error": f"Сбой в матрице гипноза: {str(e)}"},
|
||||
{"error": f"Glitch in hypno matrix: {str(e)}"},
|
||||
)
|
||||
|
||||
return render(
|
||||
@@ -338,7 +338,7 @@ def publish(request: HttpRequest) -> HttpResponse:
|
||||
return render(
|
||||
request,
|
||||
"block/publish_status.html",
|
||||
{"error": "Нет данных SVG для публикации. Попробуйте сгенерировать заново."},
|
||||
{"error": "No SVG data for publication. Please try generating again."},
|
||||
)
|
||||
|
||||
visitor_uuid = request.COOKIES.get("hypn0_vid")
|
||||
@@ -411,7 +411,7 @@ def publish(request: HttpRequest) -> HttpResponse:
|
||||
return render(
|
||||
request,
|
||||
"block/publish_status.html",
|
||||
{"error": f"Сбой фиксации в трансе: {str(e)}"},
|
||||
{"error": f"Failed to record in trance: {str(e)}"},
|
||||
)
|
||||
|
||||
return render(
|
||||
|
||||
Reference in New Issue
Block a user