Предыстория

Я являюсь обычным пользователем ПК и от программирования далек, пробовал что-то когда-то на 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 открыла несколько сложных вопросов, на которые мы не смогли найти однозначных ответов в документации:

  1. Реализация всплывающих иконок - возможно ли это в принципе в современных версиях Thunderbird?

  2. Управление окнами - как предотвратить конфликты между нативными уведомлениями и кастомными окнами?

  3. Таймеры и многопоточность - какие подходы работают стабильно в разных контекстах выполнения?

Если у вас есть опыт решения подобных задач или вы сталкивались с аналогичными вызовами - поделитесь решениями в комментариях!

Выводы

Разработка даже такого, казалось бы, простого расширения как переводчик, потребовала глубокого погружения в особенности платформы Thunderbird. Гибкость WebExtensions API одновременно и открывает возможности, и создает специфические ограничения.

Ресурсы, которые помогли:

Заключение

Выше выводы Deepseek, а мои такие: Разработка расширений для Thunderbird с помощью Deepseek оказалась увлекательным процессом. На разработку основного функционала было потрачено 14 часов, допиливание и переводы + 10ч.

Еще копирования переводов на сайт и пока разобрался как работать с Git, Eclipse, загрузкой на сайт Thunderbird. По итогу потратил наверное часов 30-40 (около 2х недель если считать что работал не сутками). Как по вашему сколько времени на это потратит профессиональный программист если будет писать без ИИ?

Лого кстати рисовал в Алисе ИИ.

В общем сильно не ругайте и очень жду откликов по качеству код, ну и функционалу. Репозитории с кодом и ссылки на сайт с описанием и готовым расширение ниже.

Ссылки:

Комментарии (2)


  1. Robastik
    12.11.2025 04:40

    Спасибо за историю. За историю, которые ненавидит сообщество. Ненавидит заслуженно, ибо здесь криво все и обсуждать, в-общем, нечего. Кроме того, что человек далекий от сделал то, что как-то работает. И когда этот человек найдет бесплатный доступ к более умным моделям и более удобным инструментам, его жизнь сильно изменится. От этого уже никуда не деться: интеллектуальность айти стремительно протухает. Эффективность специалиста определяется все меньше опытом собственно программирования и все больше опытом промптинга. В 99% простых задач ии прекрасно формализует, планирует, кодит, тестирует, рефакторит и документит. Программирование уже совсем не то.


    1. BuxarNET Автор
      12.11.2025 04:40

      Я согласен, что наверное нужно хотя бы понимать, то что пишет ИИ для тебя, потому что даже то что он описывает, не все мне понятно, для этого и начал учить Python. Но как помощник ИИ куда лучше чем джуниор программист и в этом я только что, выполнив эту задачу убедился. У меня есть масса начатых проектов, которые писали джуны и бросили. По итогу деньги платил, работа не доделана, а качество кода не думаю что будет там лучше. Так с таким успехом, когда нет денег на профов, лучше я сам буду дописывать то что джуны начали и будет бесплатный не хуже результат, чем платно и без результата. Вот какие выводы у меня сложились после этой работы.