Интегрирован wesp в сайт
CI / quality (push) Canceled after 0s

This commit is contained in:
влад
2026-07-17 12:57:18 +03:00
parent 5dfa06ddbe
commit 355c0ef9f1
883 changed files with 194576 additions and 177 deletions
+123
View File
@@ -0,0 +1,123 @@
"""Подсказки HTML/HTTP для киоск-Chromium: не предлагать перевод страницы."""
from __future__ import annotations
import re
from typing import Tuple
from flask import Response
# Префиксы страниц киоска (localhost / весы / загрузка).
# Киоск-страницы, где курсор мыши остаётся видимым (остальные киоск-страницы — cursor: none).
_KIOSK_CURSOR_VISIBLE_PATHS: Tuple[str, ...] = (
"/scales",
)
_KIOSK_HTML_PATH_PREFIXES: Tuple[str, ...] = (
"/scales",
"/starting",
"/setup",
"/calibration",
"/calibrate",
"/kiosk/",
"/static/startup-loading.html",
)
_HEAD_INJECT = (
'<meta name="google" content="notranslate">\n'
' <meta name="googlebot" content="notranslate">\n'
' <meta http-equiv="Content-Language" content="ru">\n'
)
_HTML_TAG_RE = re.compile(r"<html(\s[^>]*)?>", re.IGNORECASE)
_HAS_NOTRANSLATE_RE = re.compile(
r'<meta[^>]+name=["\']google["\'][^>]+content=["\']notranslate["\']',
re.IGNORECASE,
)
def is_kiosk_html_path(path: str) -> bool:
if not path:
return False
for prefix in _KIOSK_HTML_PATH_PREFIXES:
if path == prefix or path.startswith(prefix):
return True
return False
def is_kiosk_cursor_hidden_path(path: str) -> bool:
"""Скрывать курсор на киоск-страницах, кроме явных исключений (например /scales)."""
if not is_kiosk_html_path(path):
return False
normalized = path.rstrip("/") or "/"
for visible in _KIOSK_CURSOR_VISIBLE_PATHS:
if normalized == visible.rstrip("/") or normalized.startswith(visible.rstrip("/") + "/"):
return False
return True
def kiosk_translate_response_headers() -> dict[str, str]:
return {
"Content-Language": "ru",
"Google-Translate": "no",
}
def inject_no_translate_html(html: str) -> str:
"""Вставить meta notranslate и translate=no на <html> (обман встроенного переводчика)."""
if _HAS_NOTRANSLATE_RE.search(html):
patched = html
elif "<head>" in html.lower():
patched = re.sub(
r"<head>",
"<head>\n " + _HEAD_INJECT.strip().replace("\n", "\n "),
html,
count=1,
flags=re.IGNORECASE,
)
else:
patched = _HEAD_INJECT + html
def _html_repl(match: re.Match[str]) -> str:
attrs = match.group(1) or ""
if re.search(r'\btranslate\s*=', attrs, re.IGNORECASE):
return match.group(0)
if re.search(r'\bclass\s*=', attrs, re.IGNORECASE):
attrs = re.sub(
r'class\s*=\s*["\']([^"\']*)["\']',
r'class="\1 notranslate"',
attrs,
count=1,
flags=re.IGNORECASE,
)
else:
attrs = f'{attrs} class="notranslate"'
if not re.search(r'\blang\s*=', attrs, re.IGNORECASE):
attrs = f'{attrs} lang="ru"'
return f"<html{attrs} translate=\"no\">"
return _HTML_TAG_RE.sub(_html_repl, patched, count=1)
def apply_kiosk_translate_hints(response: Response, path: str) -> Response:
if not is_kiosk_html_path(path):
return response
for key, value in kiosk_translate_response_headers().items():
response.headers[key] = value
content_type = (response.content_type or "").lower()
if "text/html" not in content_type:
return response
# send_from_directory и др. — direct passthrough; get_data() падает с RuntimeError.
if getattr(response, "direct_passthrough", False):
return response
try:
html = response.get_data(as_text=True)
except (TypeError, UnicodeDecodeError, RuntimeError):
return response
if not html or "<html" not in html.lower():
return response
patched = inject_no_translate_html(html)
response.set_data(patched)
if response.content_length is not None:
response.headers.pop("Content-Length", None)
return response