Search
Write a publication
Pull to refresh

Как я навайбкодил ИИ-переводчик для браузера, потому что остальные — унылый мусор

Level of difficultyMedium
Reading time2 min
Views4.8K

GitHub → krakotay/ai-translator-chrome
Пока только для Chromium-браузеров.

Зачем вообще это всё

Google Translate — неплох, но переводит сухо, глупо, а иногда — просто криво.

пример
Мой (через gemini 2.5 flash lite)
Мой (через gemini 2.5 flash lite)
google translate
google translate

DeepL — качественнее, но:

  • часто теряет часть текста

  • не работает с встроенным текстом на странице — только через попап

  • и да, он просто не встроен в браузер нативно

А ведь очевидно: для перевода идеально подошёл бы ИИ-переводчик, вроде GPT или Claude. Но готовых решений я не нашёл. То, что есть в open source — либо мертво, либо ужасно.

пруф

Т.н. AI Translate на самом деле гуглоперевод. По остальному там тухло

Поэтому я решил: навайбкодим своё.

My Honest Opinion про css
(да, я его боюсь)
(да, я его боюсь)

Как устроено расширение

Идея простая: взять контекстный фрагмент DOM, в котором находится выделенный текст → перевести его через ИИ → вставить обратно без ломания страницы.

Вот базовая схема архитектуры:

 content.ts (выделение и разметка текста)
 ↓
 background.ts (прокси из-за ограничений расширений)
 ↓
 openaiTranslator.ts (через OpenRouter API → модель → перевод)
 ↓
 content.ts (вставка перевода)

Стек:

  • React + Vite

  • TypeScript

  • OpenRouter API (Claude, Gemini, GPT-4, Qwen и т.д.)

  • Браузерный manifest v3

  • Vibe-IDE: Windsurf


Пример кода: как я собираю текстовые узлы

// Проходит по всему поддереву и собирает видимые Text-ноды
function collectVisibleTextNodes(root: Node) {
  const out: { node: Text; original: string }[] = [];
  const walker = document.createTreeWalker(
    root,
    NodeFilter.SHOW_TEXT,
    {
      acceptNode(node) {
        if (!node.nodeValue?.trim()) return NodeFilter.FILTER_REJECT;

        const el = node.parentElement as HTMLElement | null;
        if (!el) return NodeFilter.FILTER_REJECT;
        const cs = getComputedStyle(el);
        if (cs.display === "none" || cs.visibility === "hidden") {
          return NodeFilter.FILTER_REJECT;
        }
        return NodeFilter.FILTER_ACCEPT;
      },
    }
  );

Функция проходит по дереву и собирает только видимые текстовые ноды. Это позволяет не переводить скрытый или технический мусор. Одна из прошлых реализаций переводила вообще всё, весь HTML. Работало качественно, но дольше, и вызвало большой расход токенов. Сейчас это исправлено.

Перевод происходит прямо в контексте, что особенно приятно на страницах типа документации или форумов.

OpenRouter: любой ИИ на выбор

Я использовал OpenRouter endpoint, потому что:

  • даёт доступ к десяткам моделей (Claude 4, GPT-4.1, Gemini 2.5 Flash и т.д.)

  • можно выбрать любую модель прямо в настройках

  • можно платить криптой, даже из России.

💸 Сколько стоит?

Я сам пользуюсь каждый день. За месяц потратил $0.16 — и это с тестами и перерасходами.
Для бытового перевода — почти бесплатно.


Что можно улучшить?

Сейчас работает стабильно и качественно. Достаточно, чтобы я пользовался каждый день. Мои идеи на вырост:

  • сделать нормальный UI выбора модели

  • добавить буфер оригинала / восстановления

  • перерисовать иконку (сейчас времянка)

  • можно сделать полноценный сервис с аккаунтами и настройками

  • Порт на Firefox

  • Выбор своего сервера (сейчас возможность выбора LM Studio отключена).

    Но сервис - слишком сложно, остальное "не горит". Но "по просьбам трудящихся" могу заняться.


Заключение

Идея оказалась проще, чем я думал. Работает приятно, пользуюсь сам — почти как встроенная функция браузера.

Почему такого до сих пор никто не сделал — не понимаю.
Обратная связь на гитхабе и в комментариях всячески приветсвуется.

👾 https://github.com/krakotay/ai-translator-chrome

Tags:
Hubs:
+10
Comments24

Articles