- Мгновенный перевод выделенного текста
- Поддержка 100+ языков
Как я разработал переводчик для Thunderbird с помощью Deepseek: от идеи до публикации в официальном магазине
Предыстория
Я являюсь обычным пользователем ПК и от программирования далек, пробовал что-то когда-то на 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
BuxarTranslate - переводчик для Thunderbird...