Как я создал переводчик для Thunderbird на чистом JavaScript с помощью Deepseek: от задумки до релиза в официальном каталоге
Вступление: откуда взялась идея
Я обычный пользователь компьютера, и программирование для меня — непознанная территория. Единственный опыт, если его можно так назвать, сводится к базовым экспериментам с HTML и PHP еще в далеких двухтысячных. Сейчас изучаю Python онлайн, но что я сделал — сделано практически без понимания кода.Мотивация появилась из рутины: работая с международной перепиской в Thunderbird, постоянно приходилось копировать текст в браузер для перевода и возвращать обратно. Это отнимало кучу времени. В голову пришла мысль — а почему бы не встроить переводчик прямо в почтовый клиент? На момент задумки подобных решений не существовало, поэтому я решил создать его сам. Плюс, прочитав про Vibe Coding, захотелось попробовать на практике.Для реализации выбрал Deepseek — мощный бесплатный ИИ, которым на тот момент мало кто пользовался для создания ПО (все вокруг обсуждали платный GPT-4). Решил проверить, на что способен. Все технические детали и описание трудностей тоже сгенерировал с его помощью.
Что использовал для разработки
- Язык: JavaScript (WebExtensions API)
- Платформа: Thunderbird 78.0+
- API перевода: Google Translate
- Инструменты: Eclipse, Git, GitHub
Структура проекта
CopyBuxarTranslate/
├── src/ # Исходники │
├── background.js # Фоновый скрипт │
├── content.js # Работа с DOM │
└── popup/ # Всплывающий интерфейс
├── docs/ # Документация
├── scripts/ # Скрипты сборки
└── build/ # Собранные пакеты
Что получилось реализовать
1. Двойной вывод перевода
JavaScriptCopyfunctionshowTranslation(originalText, translatedText){// Быстрое уведомление browser.notifications.create({type:"basic",title:"Перевод",message: translatedText.substring(0,100)+"..."});// Детальное окноshowDetailedWindow(originalText, translatedText);}
2. Добавление в контекстное меню
JavaScriptCopybrowser.menus.create({id:"translate-text",title:"Перевести на %s",contexts:["selection"]}); browser.menus.onClicked.addListener((info, tab)=>{if(info.menuItemId==="translate-text"){translateSelectedText(info.selectionText);}});
3. Поддержка 6 языков интерфейса
Английский, русский, немецкий, испанский, французский, итальянский через систему локалей Thunderbird.
Реальные проблемы и как с ними боролся
Проблема 1: Иконка у выделенного текста
Задача: Показывать иконку перевода сразу после выделения текста в письме — как в браузере.Почему не сработало (по мнению Deepseek):
- Ограничения API Thunderbird для работы с выделением
- Сложности с позиционированием элемента
- Конфликты с системным меню
Неудачная попытка:JavaScriptCopydocument.addEventListener('selectionchange',function(){const selection =window.getSelection();if(selection.toString().trim()){showTranslateIcon(selection.getRangeAt(0));}});Вопрос читателям: Кто-то реализовал такое в Thunderbird? Какие API использовать?
Проблема 2: Конфликт окон и системных уведомлений
Задача: Открывать окно перевода под иконкой, но оно мгновенно закрывалось нативными уведомлениями Thunderbird.Пробовал:
- Прямое открытие окна — закрывалось сразу
- Задержка setTimeout — не помогала
- Отключение уведомлений — терял функционал
Решение: Отказался от привязки к панели, сделал отдельное независимое окно.Вопрос сообществу: Как правильно управлять жизненным циклом окон в расширениях Thunderbird?
Проблема 3: Таймер в окне перевода
Задача: Отсчет секунд для показа прогресса.Проблема: Таймер то зависал, то показывал неправильное время.JavaScriptCopylet seconds =0;const timer =setInterval(()=>{ seconds++;document.getElementById('timer').textContent= seconds +' сек';},1000);// Сбивался постоянноВопрос: Как работать с таймерами в окнах расширений Thunderbird?
Проблема 4: Проверка безопасности при публикации
Задача: Пройти модерацию в официальном магазине.Что не нравилось валидатору (по верси Deepseek):
- eval() в коде
- Потенциальные XSS-уязвимости
- Небезопасные вызовы внешних API
На самом деле проблема была с HTML-кодом внутри JavaScript — валидатор не пропускал. Deepseek быстро переписал все на чистый JS.Фикс:JavaScriptCopy// Было (опасно):const result =eval('('+ jsonResponse +')');// Стало:const result =JSON.parse(jsonResponse);// Было (XSS): element.innerHTML= userContent;// Стало: element.textContent= userContent;
Проблема 5: Контекстное меню в разных версиях Thunderbird
Решение: Универсальный код с проверкой возможностей:JavaScriptCopyif(browser.menus.onShown){ browser.menus.onShown.addListener(handleContextMenu);}else{ browser.menus.create({/* базовое меню */});}
Проблема 6: Автозакрытие при потере фокуса
Задача: Закрывать окно при клике вне его.Пробовал разные методы:
- window.addEventListener('blur') — нестабильно
- Проверка кликов не в окне — закрывало и внутри
- Page Visibility API — по-разному работало на ОС
- requestAnimationFrame — высокая нагрузка
Временное решение: Кнопка закрытия, таймер, стандартное поведение ОС.Вопрос: Есть ли кроссплатформенное решение для Windows/Linux/macOS?
Как опубликовал расширение
1. Сборка пакета
bashCopyzip-r buxartranslate.xpi src/ manifest.json locales/
2. Загрузка на addons.thunderbird.net
- Верификация аккаунта разработчика
- Загрузка XPI-файла
- Заполнение метаданных
- Прохождение модерации
3. Многоязычное описание
Использовал HTML-форматирование для красивого вида на странице расширения.
Производительность
- Версия: 1.0.1
- Размер: ~250 KB
- Время загрузки: < 2 сек
- Поддержка: Thunderbird 78.0+
Планы
- API Яндекс.Переводчик
- Перевод всего письма целиком
- Словарь с сохранением переводов
- Голосовое воспроизведение
Вопросы к опытным разработчикам
- Всплывающие иконки — вообще реально в Thunderbird?
- Управление окнами — как избежать конфликтов с нативными уведомлениями?
- Таймеры — какие подходы работают стабильно?
Если у вас есть опыт — поделитесь в комментариях!
Мои итоги (не Deepseek)
Deepseek говорит красиво, а я так считаю: разработка с ИИ — увлекательный процесс. На основной функционал ушло 14 часов, доработки и переводы — еще 10. Плюс освоение Git, Eclipse, публикация... Всего около 30-40 часов (2 недели по вечерам).Сколько бы потратил профи без ИИ? Интересно сравнить.Логотрисовал в Алисе (ИИ).Не судите строго по коду — я новичок. Жду фидбэка!Ссылки: