Створюємо англо-український словник для Kindle: від Римської імперії до AI
Мене звати Павло Ляпін, я CTO у компанії Vault12. Наша українська команда розробляє мобільне рішення для зберігання приватних даних. Але ця стаття про мій мініпроєкт, який почався як «справа на пару вечорів».
Я живу у місті Остін, штат Техас. Переїжджаючи сюди у
Одна з переваг США — культура електронних книжок. Читалка тут є майже в кожному домі. Я теж читаю на Kindle, переважно англійською. Але яким би fluent не був English, завжди трапляються слова на кшталт fusiform чи putrefaction, які миттєво вибивають зі стану потоку. Поки не дізнаєшся переклад, далі читати неможливо. Принаймні, з моєю допитливістю.
На щастя, Kindle вміє показувати значення слів з вбудованого словника. На моєму пристрої передвстановленими виявилися тільки English Oxford Dictionary та (чомусь) англо-арабський словник. Англійські синоніми не завжди допомагають зрозуміти точне значення, а українського словника просто не було.
Тож я вирішив зробити його сам. Слова з прикладу, до речі, реальні: зустрівши їх на одній сторінці, я зрозумів, що час діяти. Справа ж на пару днів, що може піти не так?
Пошук сорсу або як знайти голку в стозі сіна
Отже, потрібен словник. Здавалося б: 2024 рік, інтернет, open source, все давно оцифровано. Ну, не зовсім. Англо-українських словників у відкритому доступі практично не існує. Є Google Translate, але він не завжди розуміє контекст і любить перекладати «bank» як «банк», навіть коли мова про берег річки. Є ChatGPT, але він іноді галюцинує українською так, ніби вчив мову за оголошеннями на OLX (що може бути правдою).
Після кількох годин пошуків я натрапив на репозиторій bakustarver/ukr-dictionaries-list-opensource, скарбницю українських офлайн-словників. Там окрім вузько спеціалізованих причаївся Англо-український словник М.І. Балла — 75 000 статей! Саме те, що треба.
Тепер питання авторського права. Видавництво «Освіта», яке випустило цей словник у 1996 році, вже не існує. Автора теж не вдалося знайти — мабуть, у
Крок −1. Вибір технології
Грудень
У підсумку всі сотні ітерацій написала LLM, а я лише іноді втручався, коли вона робила щось зовсім дивне. Вайб-кодинг до того, як це стало мейнстрімом. До речі, за наступний рік той особливий дофамін здогадуватись, як саме модель вас не зрозуміє, почав притуплятися.
Крок 0. Формат вхідних даних
У репозиторії словник був у кількох форматах. Я вибрав DSL (Dictionary Source Language), бо виглядало найпростіше. Кожен рядок: слово, табуляція, переклад з HTML-розміткою:
fusiform <div style="margin-left:1em"><i class="p"><font color="green">adj</font></i></div> <div style="margin-left:1em">веретеноподібний</div>
Виглядає просто. Напевно ж працівники Amazon зробили інтуїтивний спосіб завернути будь-що в словник для їх читалки, щоб продажі книжок серед іноземців постійно зростали. Скоро побачимо.
Крок 1. Зайві метадані
Досить тривіально видалити рядки з кінця і початку файлу, де вказані метадані — вони не знадобляться для фінальної версії словника.
# Видаляємо рядки з "_about" або "##"
if first_column == "_about" or first_column.startswith("##"):
continue
Також виявилось, що деякі статті містять пояснення у фігурних дужках, наприклад
Tanganyika{, Lake}Це не особливо допомагає, тому що у англомовній книзі слово не зустрінеться саме у такому форматі. Відрізаємо regexp-ом.
Крок 2. Об’єднання перехресних посилань
Наступне відкриття: багато статей словника — це просто посилання на інші статті:
abnormity <div><font color="green">див.</font> <<abnormality>></div>
Було б непогано натиснути на посилання і перейти на іншу статтю, правда? От тільки читалки Kindle так не вміють. Навіть найновіші моделі. Тому якщо залишити як є, читач замість перекладу отримає ще одне англійське слово. Не дуже корисно.
Рішення: об’єднуємо такі статті. Скрипт шукає
<font color="green">див.</font>і додає синоніми до основної статті.
Крок 3. Британія проти Америки: Colour vs Color
Продивляюсь словник і думаю, що він майже готовий. Перевіряю слово organize, а його немає. Як так? Невже не існувало у
А, ну так. Словник перекладає королівську британську англійську. А американці, як відомо, не дуже дотримуються орфографії з метрополії.
VarCon на допомогу
Розгублена LLM каже, що ніяких вбудованих строкових методів на Python для «суржизації» англійських слів через Атлантичний океан не існує. Що ж, будемо шукати.
Знаходимо VarCon (Variant Conversion Info) — пани Kevin Atkinson та Benjamin Titze підтримують текстовий файл з відмінностями між британською, американською, канадською та австралійською орфографіями. На попередньому кроці ми (а точніше контекст нашої
Що отримуємо?
На борту тепер:
- tire на додачу до tyre;
- enroll замість enrol;
- smolder замість smoulder;
- aging замість ageing;
- ціла плеяда різних -ize на місці -ise;
- та -er замість -re (center/centre, fiber/fibre).
Якщо є colour, автоматично додаємо color як синонім. Повіримо Кевіну та Бенджаміну на слово, а канадців і австралійців поки пропустимо. Перший у світі австралійсько-український словник залишаємо як вправу для читача.
Крок 4. Іменники: однина, множина та кактуси
Словник скомпільовано, завантажено на Kindle. П’ять хвилин читання — і нова проблема. Виділяю слово books. Kindle каже: «Такого слова не існує». Серйозно?
Нерегулярні множини іменників
Окрім шкільних child/children та mouse/mice, є купа менш очевидних. Словник частково про них знає:
cacti <div><font color="green">pl</font> <<cactus>></div>
І ось вона — Римська імперія з клікбейтного заголовку! Англійська запозичила з латини та грецької близько
- cactus | cacti → одна стаття;
- aquarium | aquaria → одна стаття;
- alumnus | alumni → одна стаття;
- antenna | antennae → одна стаття.
Бонус-факт: деякі слова мають три варіанти множини. Octopus → octopuses (англійська), octopi (псевдо-латина), octopodes (справжня грецька!). А «data» і «media» технічно множини від datum і medium, але сучасна англійська використовує їх як однину. Лінгвістична еволюція в дії.
Регулярні іменники та бібліотека inflect
З рештою іменників теж не все просто — не можна просто додати -s у кінці. Є досить багато виключень. Підключаємо inflect:
import inflect
p = inflect.engine()
p.plural("book") # → "books"
p.plural("city") # → "cities"
p.plural("box") # → "boxes"
Бібліотека знає правила утворення множини: коли додавати -s, коли -es, коли змінювати y на ies.
Цікавий трюк: inflect має метод singular_noun(word), який повертає false для слів в однині, і базову форму для слів у множині. Це дозволяє уникнути неправильних значень типу bookss:
p.singular_noun("books") # → "book" (це множина)
p.singular_noun("book") # → False (це однина, не чіпаємо)
Для ваших проєктів: inflect стане у пригоді для:
- Генерації правильних закінчень у повідомленнях («1 item» vs «5 items»);
- Роботи з числівниками (перетворення чисел у слова);
- Визначення артиклів (a/an).
Крок 5. Прикметники: великий, більший, найбільший
Наступний рівень складності — прикметники. В англійській мові є три ступені порівняння:
- large (positive)
- larger (comparative)
- largest (superlative)
І знову проблема: виділяєш на Kindle слово larger, а словник мовчить — у ньому є тільки large. Сам тільки Inflect тут вже не допоможе, тож доводиться шукати інші бібліотеки.
SpaCy + PyInflect
Для генерації форм прикметників використовуємо комбо spaCy + pyinflect:
import spacy
import pyinflect
nlp = spacy.load("en_core_web_sm")
doc = nlp("large")
token = doc[0]
token._.inflect("JJR") # → "larger" (comparative)
token._.inflect("JJS") # → "largest" (superlative)
SpaCy — це потужна NLP-бібліотека, яка розуміє структуру мови. PyInflect додає до неї можливість генерувати словоформи.
Для ваших проєктів: SpaCy використовується для:
- Аналізу тексту (визначення частин мови, іменованих сутностей);
- Лематизації (знаходження базової форми слова);
- Машинного перекладу та NLP-задач.
Крок 6. Дієслова: найскладніший бос
Якщо ви думали, що з іменниками та прикметниками було складно — welcome to the verb zone.
В англійській дієслово може мати до 5 різних форм:
- write (base form)
- writes (3rd person singular)
- wrote (past tense)
- written (past participle)
- writing (gerund/-ing form)
Нерегулярні дієслова
Знову починаємо з нерегулярних форм. Словник знає базові шкільні варіанти:
wrote <div><font color="green">past</font> від <<write>></div> written <div><font color="green">p.p.</font> від <<write>></div>
Збираємо всі такі зв’язки у CSV-файл, а потім об’єднуємо зі статтею основного дієслова:
write | wrote | written | writes | writing
Регулярні дієслова
Для регулярних дієслів знову використовуємо SpaCy + PyInflect:
doc = nlp("walk")
token = doc[0]
token._.inflect("VBD") # → "walked" (past tense)
token._.inflect("VBN") # → "walked" (past participle)
token._.inflect("VBG") # → "walking" (gerund)
token._.inflect("VBZ") # → "walks" (3rd person)
Penn Treebank POS Tags
Ці загадкові коди (VBD, VBN, VBG, VBZ, JJR, JJS) — це Penn Treebank Part-of-Speech Tags, стандарт маркування частин мови в англійській NLP:
|
Тег |
Значення |
Приклад |
|---|---|---|
|
VB |
Base verb |
write |
|
VBD |
Past tense |
wrote, walked |
|
VBN |
Past participle |
written, walked |
|
VBG |
Gerund |
writing, walking |
|
VBZ |
3rd person singular |
writes, walks |
|
JJ |
Adjective |
large |
|
JJR |
Comparative |
larger |
|
JJS |
Superlative |
largest |
|
NN |
Noun singular |
book |
|
NNS |
Noun plural |
books |
Ймовірно, можна було з цього почати і в попередніх кроках. Але велику частину шляху вже пройдено.
Крок 7. Збірка всіх словоформ
Після всіх етапів у нас є:
- Нерегулярні множини іменників (з самого словника).
- Регулярні множини іменників (згенеровані inflect).
- Всі форми прикметників (згенеровані spacy + pyinflect).
- Нерегулярні форми дієслів (з самого словника).
- Регулярні форми дієслів (згенеровані spacy + pyinflect).
Об’єднуємо всі CSV-файли та додаємо до основного словника:
csv_paths = [ "temp/nouns-regular.csv", "temp/adjectives.csv", "temp/regular.csv" ]
На виході маємо словник, де кожна стаття містить всі можливі форми слова.
Крок 8. Чистка розмітки
Оригінальний словник містить специфічну для свого формату HTML-розмітку:
<i class="p"><font color="green">n</font></i> <font color="green">юр.</font> <font color="darkred"><b>1.</b></font> <div style="margin-left:1em">...</div>
На чорно-білому Kindle кольори не відображаються. Замінюємо на курсив, підкреслення тощо. Деякі кольори так і не вдалося розшифрувати — просто видаляємо:
# Видаляємо зайве content = re.sub(r'<font color="green">(.*?)</font>', r'\1', content) # Замінюємо <i class="p"> на <em>, який коректно відображається на Kindle content = re.sub(r'<i class="p">(.*?)</i>', r'<em>\1</em>', content) # Конвертуємо внутрішні посилання content = re.sub(r"<<(.*?)>>", r'<a href="#\1">\1</a>', content)
Крок 9. Фінальна конверсія в XHTML
Kindle використовує специфічний формат для словників — XHTML з особливими тегами:
<idx:entry name="default" scriptable="yes" spell="yes"> <h5><dt> <idx:orth value="book">book <idx:infl> <idx:iform value="books" /> </idx:infl> </idx:orth></dt></h5> <dd>книга, книжка</dd> </idx:entry>
Що тут що:
- <idx:entry> — стаття словника;
- <idx:orth> — основне слово (headword);
- <idx:infl> — альтернативні форми (inflections);
- <idx:iform> — кожна окрема форма.
Офіційної документації немає. Єдиний спосіб — шукати інші саморобні словники на GitHub і розбиратися по їхньому коду.
Оскільки словник величезний (75 000+ статей), розбиваємо на кілька файлів по 15 000 записів. Інакше конвертер задихається, принаймні на моєму девайсі.
Крок 10. Повний пайплайн
Запускаємо python main.py — і 14 скриптів виконуються послідовно:
scripts = [ "00.sanitize.py", # Чистка метаданих "01.crosslinks.py", # Об'єднання перехресних посилань "02.varcon-csv.py", # Парсинг британсько-американських варіантів "03.variants.py", # Застосування варіантів "04.irregular-nouns.py", # Екстракція нерегулярних множин іменників "05.filter-irregular-nouns.py", # Мерж нерегулярних множин іменників "06.regular-nouns.py", # Генерація регулярних множин "07.adjectives.py", # Генерація ступенів порівняння прикметників "08.filter-irregular-verbs.py", # Мерж нерегулярних форм дієслів "09.irregular-verbs.py", # Екстракція нерегулярних форм дієслів "10.regular-verbs.py", # Генерація регулярних дієслівних форм "11.all-inflections.py", # Об'єднання всіх словоформ "12.clean-markup.py", # Чистка HTML-розмітки "13.convert-to-xhtml.py",# Конверсія в XHTML для Kindle ]
Як зростає словник на кожному етапі:
|
Етап |
Словоформ |
|---|---|
|
Початок (сирі дані) |
79 355 |
|
Після об’єднання посилань |
79 300 |
|
Після британсько-американських варіантів |
80 700 |
|
Після всіх словоформ |
155 622 |
Майже вдвічі більше слів, ніж на старті. Залишається скомпілювати в MOBI через Kindle Previewer — і готово.
Підсумки
Отже, що вийшло? Фінальний словник містить понад 75 000 статей та 155 тисяч словоформ — це з урахуванням усіх множин, дієслівних форм, ступенів порівняння та британсько-американських варіантів. Працює на всіх моделях Kindle, від найстаріших до Scribe.
Щодо бібліотек: inflect виявився незамінним для роботи з іменниками, а комбо spaCy + pyinflect закрило всі потреби з дієсловами та прикметниками. Якщо колись будете працювати з англійською морфологією, раджу почати саме з них.
Окрема подяка Jake McCrary за статтю про формат словників Kindle та авторам English-Persian Dictionary за робочі скрипти, з яких я багато чого підгледів.
Словник можна завантажити і користуватися. Просто скиньте файл на Kindle через Calibre, виберіть його як словник за замовчуванням — і вперед читати. Код відкритий, тож якщо хочете адаптувати для іншої мови або інших читалок — форкайте.
Якщо ви володієте правами на цей словник — напишіть мені, і я або видалю проєкт, або (що було б значно краще) отримаю дозвіл і вкажу коректну ліцензію. Тим часом маємо що маємо: видавництво не існує, автора не знайти, ліцензія невідома.
А якщо ви представник держави і чомусь дочитали до цього місця — підтримка офіційного open-source словника звучить як задача для профільного міністерства. Трохи дивно, що у 2025 році це має робити хтось невідомий з інтернету у вільний час.
Буду радий фідбеку в коментарях!
P.S. Fusiform — веретеноподібний. Putrefaction — гниття. Тепер ви знаєте.
P.P.S. Справа на «пару днів» зайняла три тижні. Але воно того варте.
Сподобалась стаття? Підписуйтесь на автора, щоб отримувати сповіщення про нові публікації на пошту.
10 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів