← Blog

Самоперекладаючий блог: SQLite, редактор Markdown та локальна LLM

DEENESRUUK

Цей блог має трохи незвичайну властивість: я пишу допис один раз, англійською мовою, а локальна мовна модель створює російську та українську версії. Ось ця механістика — і, як завжди, де я навмисно вивів модель за межі критичного шляху.

Дописи — це дані, а не файли

Перша версія блогу зберігала кожен допис як файл Markdown, скомпільований під час збірки. Це було добре для розробника, але марно для редагування "на льоту" — кожна правка означала перезбірку та деплой. Тому дописи перемістилися в SQLite, один рядок на (slug, language), а Markdown рендериться в HTML під час запиту.

Ця одна зміна розблокувала все інше: адміністративний редактор. За /admin, доступний лише за паролем, знаходиться простий редактор Markdown — заголовок, slug, теги, велике поле вмісту та перемикач Опубліковано. Написання чи виправлення допису тепер — це просто текстове поле та кнопка "Зберегти", без жодного етапу збірки.

Одна кнопка, дві мови

Сайт тримовний (EN / RU / UK), і підтримувати синхронізацію трьох написаних вручну копій кожного допису — це саме той вид рутинної роботи, який виснажує. Тому поруч з кожним англійським дописом є кнопка “Translate → RU & UK”.

Натисніть її, і сервер передасть допис локальній моделі Gemma (через Ollama у локальній мережі — жоден текст не залишає мережу). Суворий промпт наказує їй перекласти заголовок, опис та вміст, зберігаючи весь Markdown, блоки коду, URL та технічні терміни (SQLite, BGP, імена файлів`) точно такими, як вони написані. Переклад відбувається у фоновому режимі — мовні моделі витрачають час — і результат зберігається як чернетка.

Це слово має значення. Переклади ніколи самі не публікуються. Вони потрапляють як чернетки, щоб я міг їх прочитати, виправити будь-яку дивну незграбну фразу (особливо в українській мові), і лише потім перевести їх у "живий" стан. Модель створює перший варіант; підписує його людина.

Сторона читача

Кожен допис потрапляє на три URL-адреси — /blog/..., /ru/blog/..., /uk/blog/... — з невеликим перемикачем мови в статті, який показує лише ті версії, які насправді опубліковані. Кожна сторінка має свою канонічну URL-адресу, структуровані дані BlogPosting у своїй мові та запис у sitemap, щоб пошукові системи бачили три належним чином локалізовані статті, а не одну сторінку з параметром запиту.

І оскільки чесність дешева, а довіра — ні, кожен допис та індекс блогу містять коротку довідкову примітку: більшість дописів створено за допомогою ШІ, а версії RU/UK є машинівно перекладеними та відредагованими.

Та сама принципова схема, знову

Якщо ви читали інші дописи тут, ви впізнаєте форму. LLM — це помічник із чернеток та перекладник, а не джерело істини — цим є рядок SQLite. Він працює осторонь, на вимогу, створюючи чернетки, які затверджує людина; якщо Gemma вийде з ладу, блог цього не помітить, мені просто поки що не буде свіжого перекладу.

Мовна модель — чудовий спосіб почати речення іншою мовою. Це погане місце для завершення редакторського рішення. Цей блог побудований навколо цієї лінії.

Прозорість: більшість дописів тут створено за допомогою ШІ, а неанглійські версії перекладені локальною LLM і вичитані. Помітили помилку? Напишіть мені.