Selection Translator — компактное расширение для Chromium-браузеров, которое переводит выделенный текст прямо на странице. Выделите фрагмент, нажмите Перевести или Скопировать — результат появится в аккуратной плавающей панели без перехода на отдельный сайт.
Проект сделан как Manifest V3-расширение и подходит для Chrome, Yandex Browser и других Chromium-браузеров, которые поддерживают нужные API расширений.
- Плавающая панель действий рядом с выделенным текстом.
- Перевод в небольшом окне со скроллом для длинных фрагментов.
- Копирование исходного текста и готового перевода.
- Нативное контекстное меню браузера для выделенного текста.
- Настройки провайдера, языка перевода, лимита символов и поведения панели.
- Поддержка Google web, Yandex Cloud Translate и эндпоинта, совместимого с LibreTranslate.
- Устойчивость к ограничению доступа со стороны Google: цепочка адресов, кэш, паузы и переход на второго провайдера.
- Настраиваемая прозрачность панели с размытием фона.
- Выделите текст на любой обычной веб-странице.
- Нажмите
Перевестив плавающей панели. - Проверьте перевод в небольшом окне рядом с выделением.
- Скопируйте исходный текст или перевод одной кнопкой.
- При необходимости поменяйте провайдера и язык в настройках расширения.
- Склонируйте репозиторий.
- Установите зависимости:
npm ci. - Соберите расширение:
npm run build. - Откройте в браузере страницу
chrome://extensions. - Включите режим разработчика.
- Нажмите
Загрузить распакованное расширение. - Выберите папку
dist/.
После изменений в TypeScript-коде или manifest.json запустите npm run build и перезагрузите расширение на странице расширений.
| Команда | Что делает |
|---|---|
npm run typecheck |
Проверяет TypeScript в строгом режиме без записи файлов |
npm test |
Запускает тесты через встроенный Node.js test runner и tsx |
npm run build |
Собирает рабочее Manifest V3-расширение в dist/ |
npm run verify |
Запускает typecheck, тесты и сборку |
npm run pack |
Собирает zip-архив расширения из dist/ в outputs/ |
Готовый архив появляется здесь:
outputs/selection-translator-extension.zip
Папки dist/ и outputs/ не версионируются.
В репозитории настроены два процесса.
CI запускается на pull request, push в main и вручную через GitHub Actions. Он:
- запускает
npm run verify; - проверяет, что расширение собирается через
npm run pack.
CD запускается только при отправке git-тега версии, например v1.0.0 или v1.0.
Перед публикацией релиза CD-процесс:
- приводит короткий тег вида
v1.0к версии1.0.0; - сверяет версию тега с
versionвpackage.json; - сверяет версию тега с
versionвmanifest.json; - запускает проверки;
- собирает zip-архив;
- публикует GitHub Release с архивом расширения.
Пример релиза:
git tag v1.0.0
git push origin v1.0.0Если номер тега не совпадает с версиями в package.json и manifest.json, релиз остановится.
| Путь | Назначение |
|---|---|
manifest.json |
Конфигурация Manifest V3 расширения, указывает на JS-файлы в собранном dist/ |
src/ |
TypeScript-код content script, background service worker, настроек и переводчиков |
popup/ |
Popup расширения: HTML/CSS и TypeScript entrypoint |
options/ |
Страница настроек: HTML/CSS и TypeScript entrypoint |
assets/ |
Иконки расширения |
scripts/ |
Сборка TypeScript-исходников в рабочий dist/ |
tests/ |
Тесты manifest, UI-скриптов, настроек и переводчиков |
.github/workflows/ |
CI и CD сценарии GitHub Actions |
Расширение умеет работать с несколькими провайдерами:
- Google web;
- Yandex Cloud Translate;
- эндпоинт, совместимый с LibreTranslate.
Для провайдеров, которым нужны ключи или собственный эндпоинт, значения задаются в настройках расширения и не хранятся в репозитории.
Google web работает без ключа, поэтому доступ ограничивается по IP-адресу и отвечает 429 со страницей «Sorry... automated queries». Чтобы перевод не падал, расширение делает так:
- запрос идет по цепочке из трех адресов Google, начиная с
clients5.google.comс клиентомdict-chrome-ex, который отвечает даже там, гдеtranslate.googleapis.comуже отдает 429; - текст уходит в теле POST-запроса, а не в URL: длинный GET-адрес Google отклоняет с ошибкой 400 примерно от 2500 знаков кириллицы;
- запросы разнесены по времени с джиттером, а после 429 включается пауза, вместо повторного долбления адреса;
- переводы кэшируются на 30 минут, одинаковые параллельные запросы склеиваются в один;
- если Google ограничил доступ, а в настройках есть ключ Yandex Cloud или собственный эндпоинт, перевод автоматически уходит туда. Отключается галочкой «Если Google ограничил доступ, переводить через Yandex или свой endpoint».
Заголовки User-Agent и Referer расширение не подменяет: fetch их запрещает, а declarativeNetRequest потребовал бы лишних разрешений.
Панель перевода и страница настроек переработаны под задачу: сначала читается перевод, остальное не мешает.
- текст перевода идет 15 пикселями с межстрочным 1.55, а выделение со страницы чистится от табличных палок, маркеров списка, мягких переносов и разрывов строк;
- пока идет запрос, в панели видно скелет из трех строк вместо одинокой надписи, и он же не дает панели дергаться при появлении ответа;
- у кнопок появились состояния нажатия и фокуса с клавиатуры, а панель открывается коротким появлением на 170 мс, которое отключается при
prefers-reduced-motion; - прозрачность панели настраивается от 50 до 100 процентов. Просвечивает только фон: текст, рамки и тени остаются плотными, а страница под панелью размывается, поэтому перевод читается и на пестром сайте.
Страница настроек разбита на четыре раздела с описаниями, поля провайдера показываются только для выбранного сервиса, исходный язык появляется при выключенном автоопределении. Кнопка «Сохранить» активна только когда есть несохраненные изменения, а панель действий закреплена внизу окна. Ползунок прозрачности сопровождается живым превью панели поверх макета страницы.
Версия 1.3.0 добавляет настройку прозрачности панели, переработанные панель перевода и страницу настроек, а также чистку выделенного текста перед переводом.
Версия 1.2.0 переводит Google-провайдера на цепочку адресов и POST-запросы, добавляет кэш, паузы после 429 и автоматический переход на второго провайдера. В host_permissions добавлен https://clients5.google.com/*, поэтому Chrome попросит подтвердить обновленные разрешения.
Версия 1.1.1 убирает экспериментальный провайдер Yandex web, потому что он требовал подмены сетевых заголовков. Yandex Cloud Translate остаётся доступен как основной Yandex-провайдер.
Если раньше был сохранён общий API-ключ, расширение перенесёт его в ключ активного провайдера: Yandex Cloud или LibreTranslate. После сохранения настроек старое общее поле ключа удаляется из хранилища.
Названия сторонних сервисов используются только для выбора провайдера перевода. Иконки и оформление расширения остаются собственными ассетами проекта.
Apache-2.0. Подробности см. в LICENSE.
