Files
screen-translator/README.md
T
gusadmin 12f974571c
build / build (push) Successful in 7s
CI: починить гейт сегментации, он молча пропускался
Шаг был зелёным, но не проверял ничего: распознавание на раннере работает,
а шаблон искал число сразу после стрелки, тогда как в выводе между ними
стоит русское слово («-> блоков 29»). Совпадения не было, и шаг выходил
с предупреждением вместо проверки.

RenderTest теперь печатает итог машиночитаемой строкой RESULT — так же, как
selftest. Отсутствие этой строки считается провалом: значит конвейер не
доработал до конца. Пропуск остался только для случая, когда на машине нет
языкового пакета распознавания.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 16:02:31 +03:00

18 KiB
Raw Permalink Blame History

Переводчик экрана

Наводит перевод поверх английского текста прямо на экране — как Яндекс.Переводчик по фото, только для монитора. Нажал горячую клавишу → английские надписи закрылись плашками под цвет фона, на них русский текст. Остальная картинка остаётся на месте.

Работает с любой программой: игры, PDF, видео, интерфейсы, картинки — всё, что видно на экране.

  • Распознавание — встроенный в Windows OCR: офлайн, бесплатно, ничего ставить не надо.
  • Перевод — несколько движков с автоматическим переключением, если какой-то не отвечает.
  • Один файл ScreenTranslator.exe (81 КБ), без установщика и без .NET SDK.

Как пользоваться

Клавиши Действие
Ctrl+Alt+Z перевести монитор, на котором сейчас курсор
Ctrl+Alt+X выделить область рамкой и перевести её
Esc или повторное нажатие закрыть перевод
Пробел (удерживать) подсмотреть оригинал под плашками
Наведение мышью показать оригинал одного фрагмента
Клик по плашке скопировать её перевод
Ctrl+C скопировать весь перевод

Значок в трее — те же команды плюс «Проверить переводчики» и правка настроек.

Пока идёт распознавание и перевод, экран уже заморожен, а фрагменты подсвечены — видно, что программа работает. Полный цикл на мониторе 3440×1440 — около трёх секунд (0,6 с распознавание + ~2 с перевод), повтор того же текста — мгновенно из кэша.

Установка

Скачать ScreenTranslator.zip из релизов, распаковать куда угодно и запустить ScreenTranslator.exe. Всё — установщика нет, программа живёт в трее.

Релиз latest пересобирается автоматически при каждом изменении в master, так что по этой ссылке всегда лежит свежая сборка. Релизы с номером версии остаются неизменными.

Если Windows покажет «SmartScreen защитил ваш компьютер» — «Подробнее» → «Выполнить в любом случае» (файл без цифровой подписи).

Автозапуск: Win+Rshell:startup → положить туда ярлык на exe.

Требование одно: модель распознавания

Нужен установленный в Windows языковой компонент «Распознавание текста» для английского. Проверить: значок в трее → «Проверить переводчики» покажет ошибку, если моделей нет.

Ставится так: Параметры → Время и язык → Язык и регион → у английского языка ···Компоненты языка → отметить Распознавание текста. На большинстве систем уже стоит.

Настройка

Рядом с exe лежит config.json (создаётся при первом запуске). После правки — «Перечитать настройки» в трее, перезапуск не нужен.

Самое полезное:

"hotkeyTranslate": "Ctrl+Alt+Z",   // своя комбинация, если эта занята
"ocrLanguage": "en-US",            // язык оригинала на экране
"targetLang": "ru",                // на какой переводить
"overlayMode": "frozen",           // frozen — стоп-кадр; live — плашки поверх живого экрана
"captureScope": "monitor",         // monitor — экран под курсором; all — все мониторы сразу
"ocrScale": 2.0,                   // 1.0 быстрее, 2.0 точнее на мелком шрифте
"detectForeign": true,             // не трогать надписи на языке системы (см. ниже)
"markTranslated": true,            // подчёркивать переведённые места
"chain": ["google", "lingva", "mymemory"]

Смешанный экран

Английская модель OCR, встретив русскую надпись, читает её как бессмыслицу вроде C03AaTb или Pa3Mep — и без защиты программа переводила бы эту кашу, залепляя плашками весь русский интерфейс.

Защита двухступенчатая:

  1. skipGarbage — отсев по форме слов: цифра посреди слова, заглавная после строчной, символы-артефакты, имена файлов.
  2. detectForeign — кадр дополнительно распознаётся моделью второго языка. Если она видит на этом месте кириллицу, надпись изначально русская и её не трогают. Это ещё примерно столько же времени на распознавание; выключается, если весь экран и так на одном языке.
  3. Список ходовых английских слов (EnglishWords.cs) — арбитр в спорных случаях. Русская модель читает латинское «Cancel» как «Сапсеl», то есть по алфавиту оно неотличимо от русского «Профиль» → npocbwlb. Если основная модель выдала узнаваемое английское слово, верим ей.

На эталонах это даёт 22 распознанных блока из 22 на английском кадре (ни одной потери) и 2 оставшихся из 20 на русском.

Совсем идеально не будет: очень мелкие надписи (вкладки браузера, 8 px) обе модели читают плохо, и часть их может проскочить. Если на экране мешанина языков — надёжнее Ctrl+Alt+X и рамка вокруг нужного куска.

Чего программа не умеет и не сможет

Рабочий стол, панель задач, списки установленных программ — не её сценарий. Подписи там это названия приложений, а отличить название от обычного слова невозможно: «Steam», «Discord», «Wand» одновременно и то, и другое. Перевод получится буквальным и бессмысленным.

Помогает "minWords": 2 — тогда переводятся только фразы от двух слов, а одиночные подписи остаются как есть. Но за это приходится платить: на интерфейсе игры теряется половина надписей («Mining», «Search», «Consumable» — тоже одиночные слова), поэтому по умолчанию стоит 1.

Про переводчики и Россию

chain — это порядок попыток. Первый ответивший движок используется, упавший временно исключается и пробуется следующий. Ничего перенастраивать при переезде в другую сеть не нужно — если Google недоступен, программа сама уйдёт на запасной.

Что стоит знать:

  • google — бесплатный публичный эндпоинт, без ключа, лучшее соотношение качества и скорости. translate.googleapis.com в России не заблокирован (замедляли YouTube, а не API), но у отдельных провайдеров ТСПУ рвёт к нему TLS. Отсюда и нужна цепочка.
  • lingva — открытый шлюз к тому же Google на других адресах. Ровно тот случай, когда напрямую не пускает, а через шлюз проходит. Медленнее (2–4 с).
  • mymemory — последний рубеж, без ключа, лимит около 5000 слов в сутки на IP.
  • yandex — самый устойчивый канал внутри РФ, но нужен платный Yandex Cloud (folderId + API-ключ).
  • deepl — лучшее качество en→ru, есть бесплатный тариф с ключом.
  • llm — перевод целым экраном через Claude API: лучше держит контекст интерфейса, но платный по токенам и медленнее.
  • libretranslate / relay — свой сервер, ничего не уходит наружу.

Проверить, что доступно из конкретной сети: трей → Проверить переводчики — покажет время ответа или ошибку по каждому.

Через прокси (например, свой sing-box в режиме mixed):

"proxy": "http://192.168.5.42:2080"

Свой релей

Если публичные сервисы недоступны, а свой сервер есть — поднимите эндпоинт, принимающий POST {"texts": [...], "from": "en", "to": "ru"} и возвращающий {"texts": [...]} той же длины, затем:

"chain": ["relay", "google"],
"engines": { "relay": { "url": "https://ваш-домен/translate" } }

Внутри релей может ходить хоть в Google, хоть в локальную модель — клиенту всё равно.

Приватность

Распознавание идёт локально, наружу уходит только распознанный текст — картинка экрана никогда не покидает компьютер. Но текст с экрана всё же уходит в выбранный сервис перевода, поэтому для чувствительного содержимого используйте libretranslate или relay на своём сервере.

Кэш переводов лежит рядом в cache.json — его можно удалять в любой момент.

Сборка из исходников

.NET SDK не нужен — используется Roslyn из Visual Studio Build Tools и сборки .NET Framework 4.8, которые уже есть в Windows.

.\build.ps1          # собрать в .\dist
.\build.ps1 -Run     # собрать и запустить
.\build.ps1 -Test    # плюс RenderTest.exe

RenderTest.exe — не сама программа, а диагностика: прогоняет весь конвейер без окна и сохраняет две картинки (как OCR разметил блоки и как лёг перевод). Запускать лучше из терминала; при двойном клике он всё равно отработает и подождёт Enter, а картинки положит в %TEMP%\screen-translator-test.

.\dist\RenderTest.exe --in кадр.png --out .\dist\test
.\dist\RenderTest.exe --scale 1.0 --no-translate

Два эталонных кадра для прогонов рисуются скриптами:

  • tools\make-sample.ps1 — англоязычный интерфейс. Проверка «всё ли переводится»: правильный результат — 22 блока.
  • tools\make-sample-ru.ps1 — русский интерфейс. Негативная проверка: английская модель OCR читает кириллицу как кашу, и её нельзя ни переводить, ни закрывать плашками. Правильный результат — около 5 блоков (мелкие обрывки вроде «Tn»), было 20 до фильтра.

Оба стоит прогонять после правок в Blocks.cs: ужесточение фильтра легко начинает резать короткие английские кнопки, и английский кадр это сразу показывает.

Флаг --expect файл.txt считает, сколько заранее известных строк реально распозналось — без такой метрики улучшение и ухудшение на глаз выглядят одинаково убедительно. --selftest проверяет биграммную модель на примерах настоящих надписей и каши.

.\dist\RenderTest.exe --in wow.jpg --expect tools\expect-wow.txt --no-translate
.\dist\RenderTest.exe --selftest

Текущие показатели (после каждой правки должны держаться):

Кадр Метрика Значение
Скриншот игры распознано известных надписей 14 из 14
Английский эталон ложно отброшено 0
Русский эталон осталось непойманной каши 2 из 20

Что внутри

Файл Зачем
src/Program.cs трей, горячие клавиши, порядок работы
src/ScreenCapture.cs снимок экрана и отдельная копия пикселей для фоновой обработки
src/Ocr.cs Windows.Media.Ocr, увеличение кадра ради мелкого шрифта
src/Blocks.cs склейка строк в абзацы, отсев каши, подбор цветов плашки
src/Translators.cs движки перевода, цепочка фоллбеков, кэш
src/PlateRenderer.cs подбор кегля и отрисовка плашки
src/OverlayForm.cs окно поверх экрана
src/RegionSelector.cs выделение области рамкой

| src/EnglishBigrams.cs | частоты буквенных пар: отличает слово от каши распознавания | | src/EnglishWords.cs | список ходовых английских слов — арбитр в спорных случаях |

Откуда взялись решения (короткий разбор чужого опыта):

  • Классические алгоритмы сегментации — RLSA, Docstrum, XY-cut, Voronoi — принимают решение «склеивать или нет» по одному сигналу, межстрочному зазору. В плотном интерфейсе он одинаков у строк абзаца и у соседних контролов, поэтому ни один из них эту задачу не решает. Работает только ансамбль независимых признаков — как в Tesseract (paragraphs.h, геометрия плюс пунктуация) и UIED, где графику детектируют отдельно от текста.
  • Отсюда четыре признака разрыва: разный фон, граница между строками, «строка не дотянула до правого края» (в абзаце короткой бывает только последняя) и несовпадение кегля.
  • Определение чужого языка — это не задача language identification: готовые детекторы (cld3, fastText) всегда выбирают какой-то язык из списка и уверенно зовут кашу английским. Нужна одноклассовая модель «похоже на настоящий английский», отсюда биграммы.
  • Проверено и отвергнуто: перевод в оттенки серого и инверсия тёмного фона перед OCR. Обещали заметный прирост, на замере не дали ничего (14 из 20 во всех вариантах), поэтому по умолчанию выключены, хотя в конфиге остались.

Тонкие места, если будете править:

  • Приложение помечено PerMonitorV2 — все координаты физические, иначе разметка OCR разъезжается с экраном при масштабе интерфейса больше 100 %.
  • OCR обводит только тело букв, без выносных элементов, поэтому плашка расширяется по вертикали — иначе сверху и снизу торчат хвосты оригинала.
  • Строки склеиваются в абзац по межстрочному интервалу и одинаковому кеглю: рваные строки переводятся заметно хуже целого абзаца.