Предыстория
Я являюсь обычным пользователем ПК и от программирования далек, пробовал что-то когда-то на HTML и PHP, но это было еще в далекие 2000г. В настоящее время начал изучать онлайн Python, а вот то что ниже сделано, сделано без знания кода вообще.
Зачем? Работая с международной перепиской в Thunderbird, я постоянно сталкивался с необходимостью переводить тексты писем. Постоянное копирование в браузер и обратно отнимало время. Так родилась идея создать расширение, которое интегрирует переводчик прямо в почтовый клиент. На момент идеи в наличии аналогов не было, по этому именно это приложение решил я реализовать. Ну кроме необходимости в данном ПО был интерес еще и по-экспериментировать начитавшись про Вайбкодинг.
Для этой работы решил использовать Deepseek как достаточно мощный ИИ из представленных бесплатных вариантов. К тому же статей по реализации на нем полноценного ПО я не видел (в основном все GPT4 на платной основе юзают), вот решил и поэкспериментировать. Далее вся техническая информация и описание проб и ошибок, тоже написана с помощью Deepseek.
Технический стек
Язык: JavaScript (WebExtensions API)
Платформа: Thunderbird 78.0+
API перевода: Google Translate
Инструменты: Eclipse, Git, GitHub
Архитектура приложения
text
BuxarTranslate/
├── src/ # Исходный код
│ ├── background.js # Фоновый процесс
│ ├── content.js # Скрипты для работы с DOM
│ └── popup/ # Всплывающее окно
├── docs/ # Документация
├── scripts/ # Скрипты сборки
└── build/ # Собранные пакеты
Ключевые особенности
1. Двойное отображение перевода
javascript
function showTranslation(originalText, translatedText) { // Мгновенное уведомление browser.notifications.create({ type: "basic", title: "Перевод", message: translatedText.substring(0, 100) + "..." }); // Детальное окно showDetailedWindow(originalText, translatedText);
}
2. Интеграция в контекстное меню
javascript
browser.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: Всплывающая иконка после выделения текста
Задача: Реализовать появление иконки перевода сразу после выделения текста в письме (аналогично Google Translate в браузере).
Почему не получилось (мнение Deepseek):
Ограничения Thunderbird API для работы с выделенным текстом
Сложности с позиционированием элемента относительно выделения
Конфликты с нативным контекстным меню
Код попытки реализации:
javascript
// Неудачная попытка показать иконку рядом с выделением
document.addEventListener('selectionchange', function() { const selection = window.getSelection(); if (selection.toString().trim()) { showTranslateIcon(selection.getRangeAt(0)); }
});
Вопрос сообществу: Есть ли работающие примеры реализации всплывающих иконок в Thunderbird расширениях? Какие API для этого использовать?
Проблема 2: Конфликт окон перевода и нативных уведомлений
Задача: Открывать окно перевода под иконкой на панели, но оно мгновенно закрывалось из-за стандартных уведомлений Thunderbird. Deepseek'у давал задачу и блокировать стандартное окно уведомлений, так он блокировал оба. Давал задачу выводить по очереди, выводил только одновременно. И самое интересное, давал задачу задержать вывод нашего на 5 секунд, пока стандартное откроется и закроется, так он смог только стандартное и задерживать и делать ему паузу 5 секунд на перед закрытием, а наше так и открывалось на доли секунды без задержки, в общем плюнул и пошли дальше.
Что пробовали:
javascript
// Попытка 1: Прямое открытие окна - закрывалось сразу
browser.windows.create({ url: "popup/translation.html", type: "popup", width: 400, height: 300
});
// Попытка 2: Задержка открытия - не работала
setTimeout(() => { openTranslationWindow(); // Все равно перекрывалось уведомлением
}, 100);
// Попытка 3: Отключение уведомлений - теряли функциональность
browser.notifications.clear("translate-notification");
Решение: Пришлось отказаться от интеграции с панелью и реализовать отдельное независимое окно перевода.
Вопрос сообществу: Как правильно управлять жизненным циклом окон в Thunderbird расширениях? Есть ли способ предотвратить автоматическое закрытие?
Проблема 3: Таймер в отдельном окне перевода
Задача: Реализовать отсчет времени в секундах в окне перевода для показа прогресса.
Проблема: Таймер работал некорректно - то зависал, то показывал неверное время.
Код проблемы:
javascript
// Таймер работал нестабильно
let seconds = 0;
const timer = setInterval(() => { seconds++; document.getElementById('timer').textContent = seconds + ' сек';
}, 1000); // Часто сбивался или останавливался
Вопрос сообществу: Какие лучшие практики для работы с таймерами в окнах Thunderbird расширений? Как синхронизировать время между разными контекстами?
Проблема 4: Проблемы безопасности при верификации
Задача: Пройти проверку безопасности при публикации в официальном магазине.
Проблемы (мнение Deepseek):
Использование
eval()в коде (унаследовано из примеров)Потенциальные XSS-уязвимости при работе с DOM
-
Небезопасные практики работы с внешними API
Я же реальные проблемы не скажу, но одну из них помню, что не пропускала валидация реализации с кодом HTML в чистом виде среди кода на javascript, Deepseek переписывал все на javascript, ну и да, были какие-то проблемы с функциями вызова объектов насколько я понял, но Deepseek справился с переписыванием для сдачи в Thunderbird очень быстро.
Решение:
javascript
// БЫЛО (опасно):
const result = eval('(' + jsonResponse + ')');
// СТАЛО (безопасно):
const result = JSON.parse(jsonResponse);
// БЫЛО (уязвимо):
element.innerHTML = userContent;
// СТАЛО (безопасно):
element.textContent = userContent;
Быстрое исправление: Анализ кода с помощью ESLint с правилами безопасности и ручной аудит всех точек ввода данных.
Проблема 5: Интеграция с контекстным меню в разных версиях Thunderbird (мнение Deepseek, я проблем в этом случае не видел, так как приложение не тестировалось на других версиях и соответственно ошибок не было)
Решение: Универсальный подход с проверкой возможностей API:
javascript
// Проверка поддержки beforeShowContextMenu
if (browser.menus.onShown) { browser.menus.onShown.addListener(handleContextMenu);
} else { // Fallback для старых версий browser.menus.create({/* базовое меню */});
}
Проблема 6: Автоматическое закрытие окна перевода при потере фокуса
Задача: Реализовать поведение, при котором окно перевода автоматически закрывается, когда пользователь кликает вне этого окна (аналогично поведению тултипов или выпадающих меню).
Что пробовали:
javascript
// Попытка 1: Отслеживание blur события на window
window.addEventListener('blur', function() { window.close(); // Не срабатывало стабильно
});
// Попытка 2: Проверка активного элемента
document.addEventListener('click', function(event) { if (!event.target.closest('.translation-window')) { window.close(); // Закрывалось даже при клике внутри окна }
});
// Попытка 3: Отслеживание фокуса через Page Visibility API
document.addEventListener('visibilitychange', function() { if (document.hidden) { window.close(); // Работало некорректно в разных ОС }
});
// Попытка 4: Проверка через requestAnimationFrame
function checkWindowFocus() { requestAnimationFrame(() => { if (!document.hasFocus()) { window.close(); } else { checkWindowFocus(); } });
}
checkWindowFocus(); // Высокая нагрузка и ложные срабатывания
Особые сложности:
В разных ОС (Windows, Linux, macOS) события фокуса работают по-разному
Окно расширения может терять фокус при системных уведомлениях
При быстром переключении между окнами возникали race conditions
Временное решение: Добавили кнопку ручного закрытия, добавили настраиваемый таймер закрытия и оставили стандартное поведение окон ОС.
Вопрос сообществу: Какие есть надежные способы отслеживания потери фокуса для окон расширений Thunderbird? Есть ли кросс-платформенное решение, которое стабильно работает в Windows, Linux и macOS?
Процесс публикации
1. Подготовка пакета
bash
# Сборка XPI-файла
zip -r buxartranslate.xpi src/ manifest.json locales/
2. Публикация на addons.thunderbird.net
Верификация аккаунта разработчика
Загрузка XPI-файла
Заполнение метаданных
Прохождение модерации
3. Поддержка многоязычного описания (видимо Deepseek рассказывает про сайт который мы тоже сляпали)
Использование HTML-форматирования для красивого отображения:
html
<strong>BuxarTranslate</strong> - переводчик для Thunderbird...
<ul>
<li>Мгновенный перевод выделенного текста</li>
<li>Поддержка 100+ языков</li>
</ul>
Производительность и оптимизация (ничего подобного в задаче не было, не знаю Deepseek реально ли ставил себе такие задачи)
Кэширование частых запросов
Ленивая загрузка ресурсов
Минимизация использования памяти
Оптимизация сетевых запросов
Статистика проекта
Версия: 1.0.1
Размер: ~250 KB
Время загрузки: < 2 сек
Поддержка: Thunderbird 78.0+
Планы на будущее (половина из написанного выдумка Deepseek)
Добавление Yandex.Translate API
Перевод целых писем
Словарь с сохранением переводов
Голосовое произношение
Обращение к сообществу
Разработка под Thunderbird открыла несколько сложных вопросов, на которые мы не смогли найти однозначных ответов в документации:
Реализация всплывающих иконок - возможно ли это в принципе в современных версиях Thunderbird?
Управление окнами - как предотвратить конфликты между нативными уведомлениями и кастомными окнами?
Таймеры и многопоточность - какие подходы работают стабильно в разных контекстах выполнения?
Если у вас есть опыт решения подобных задач или вы сталкивались с аналогичными вызовами - поделитесь решениями в комментариях!
Выводы
Разработка даже такого, казалось бы, простого расширения как переводчик, потребовала глубокого погружения в особенности платформы Thunderbird. Гибкость WebExtensions API одновременно и открывает возможности, и создает специфические ограничения.
Ресурсы, которые помогли:
Заключение
Выше выводы Deepseek, а мои такие: Разработка расширений для Thunderbird с помощью Deepseek оказалась увлекательным процессом. На разработку основного функционала было потрачено 14 часов, допиливание и переводы + 10ч.
Еще копирования переводов на сайт и пока разобрался как работать с Git, Eclipse, загрузкой на сайт Thunderbird. По итогу потратил наверное часов 30-40 (около 2х недель если считать что работал не сутками). Как по вашему сколько времени на это потратит профессиональный программист если будет писать без ИИ?
Лого кстати рисовал в Алисе ИИ.
В общем сильно не ругайте и очень жду откликов по качеству код, ну и функционалу. Репозитории с кодом и ссылки на сайт с описанием и готовым расширение ниже.
Ссылки:
Robastik
Спасибо за историю. За историю, которые ненавидит сообщество. Ненавидит заслуженно, ибо здесь криво все и обсуждать, в-общем, нечего. Кроме того, что человек далекий от сделал то, что как-то работает. И когда этот человек найдет бесплатный доступ к более умным моделям и более удобным инструментам, его жизнь сильно изменится. От этого уже никуда не деться: интеллектуальность айти стремительно протухает. Эффективность специалиста определяется все меньше опытом собственно программирования и все больше опытом промптинга. В 99% простых задач ии прекрасно формализует, планирует, кодит, тестирует, рефакторит и документит. Программирование уже совсем не то.
BuxarNET Автор
Я согласен, что наверное нужно хотя бы понимать, то что пишет ИИ для тебя, потому что даже то что он описывает, не все мне понятно, для этого и начал учить Python. Но как помощник ИИ куда лучше чем джуниор программист и в этом я только что, выполнив эту задачу убедился. У меня есть масса начатых проектов, которые писали джуны и бросили. По итогу деньги платил, работа не доделана, а качество кода не думаю что будет там лучше. Так с таким успехом, когда нет денег на профов, лучше я сам буду дописывать то что джуны начали и будет бесплатный не хуже результат, чем платно и без результата. Вот какие выводы у меня сложились после этой работы.