# Згенерувала 495 сторінок досягнень трьома мовами з експорту SQLite лише для читання, де адреса сторінки задається як дані, тож виправлення речення більше не змінювало адресу сторінки й не ламало посилання.

серпень 2026

**Ситуація.** Вміст портфоліо компанії ведуть в окремій базі даних — тій самій, з якої генерується CV, — і вебсайт має публікувати його у вигляді сторінок трьома мовами так, щоб дві копії не розходилися. Наївний підхід — писати сторінки вручну й синхронізувати їх — ламається на першому ж виправленні.

**Завдання.** Вебсайт мав генерувати свій вміст із бази даних як вхідні дані для збірки, а адреси сторінок мали залишатися незмінними, навіть коли речення на них переписують.

**Дія.** Експортер відкриває базу даних лише для читання й записує по одній сторінці на кожне досягнення кожною мовою — 495 сторінок, — а також дані таксономії та послуг, потрібні шаблонам. Він використовує лише стандартну бібліотеку, тож збірка сайту не залежить від середовища генератора, а оскільки результат закомічено, сайт збирається автономно. Найважливіше рішення в ньому стосується адрес. Раніше сайт виводив URL сторінки з перших слів її англійського формулювання, тож виправлення речення непомітно переносило сторінку й ламало всі посилання на неї: сайт, головний аргумент якого на свою користь — те, що він виправляє помилки, щоразу карав себе битим посиланням. Тепер адресу задають як дані: по одному рядку на кожну адресу кожного досягнення; перша адреса — поточна, а кожна наступна — виведена з ужитку, і для неї сайт видає перенаправлення. Під час тієї самої роботи зафіксували ще дві пастки. Порівняння періоду з текстовим стовпцем непомітно збігалося з усіма тридцятьма двома рядками через те, як база даних визначає спорідненість типів (type affinity) під час порівняння. А перелік мов тепер — єдина вісь, від якої залежать і цикл запису, і файли даних, і запити, тож додати четверту мову — це один запис у словнику, а не пошук по коду.

**Результат.** Чотириста дев'яносто п'ять сторінок генеруються з одного джерела, виправлення формулювання нічого не коштує, а всі адреси, які сайт будь‑коли публікував, і далі працюють. Експортер ухвалює рівно одне рішення щодо подання — як групувати послуги в тематичні розділи, — і це зроблено навмисно: усе інше, що він записує, належить базі даних, а якщо заголовка групи бракує якоюсь мовою, експорт зупиняється, замість того щоб показати англійський текст поверх перекладеного вмісту.

---

- Роль: Інженер з тестування та якості
- Категорії: [Frontend‑розробка](https://brand.engineer.company/uk/categories/frontend/), [Веброзробка](https://brand.engineer.company/uk/categories/web-development/), [Бази даних](https://brand.engineer.company/uk/categories/databases/), [SQL](https://brand.engineer.company/uk/categories/sql/), [Пайплайни даних (ETL/ELT)](https://brand.engineer.company/uk/categories/data-pipelines/), [Python](https://brand.engineer.company/uk/categories/python/), [Інтернаціоналізація](https://brand.engineer.company/uk/categories/i18n/)
- Послуги: [Розробка вебсайтів та CMS](https://brand.engineer.company/uk/services/web-development/), [Інтернаціоналізація та локалізація](https://brand.engineer.company/uk/services/i18n-localization/), [Розробка пайплайнів даних (ETL/ELT)](https://brand.engineer.company/uk/services/data-pipeline-development/), [Бренд, маркетинг та SEO](https://brand.engineer.company/uk/services/brand-marketing/)

<https://brand.engineer.company/uk/portfolio/generated-321-achievement-pages-from-a-sqlite-export-132/>
