Текстология
Главная
Обновления в TG
Главная
Обновления в TG

Структура словарей Hunspell: основы и составные слова

06.09.2025

Простейший способ проверки орфографии — составить словарь из правильных слов и проверять каждое слово на вхождение в этот список. Однако такой подход неудобен и неуниверсален: количество слов слишком велико. Например, одно и то же слово может иметь разные формы: дом и дома. Другой пример: слово дом будет считаться правильным даже с заглавной буквы (Дом), если оно стоит в начале предложения, а вот имя Василий должно писаться с большой буквы в любом случае. Эти и другие особенности затрудняют использование словаря в виде простого списка слов.

Библиотека Hunspell (Википедия — Hunspell) позволяет проверять орфографию с учётом морфологии и предлагает дополнительные возможности.

Словари Hunspell состоят из двух файлов: файла со словами (.dic) и файла с правилами (файл аффиксов .aff). Существует перевод документации по формату словарей, а также более полная документация в репозитории Hunspell. Далее приведены примеры работы некоторых команд из этой документации, а также ссылки на реальные словари, использующие эти команды — в основном из репозитория LibreOffice.

Для генерации примеров используется библиотека Python pyhunspell и следующий код.

import sys
from pathlib import Path

import hunspell

def check_spelling_with_hunspell(
    aff_path: str = "custom.aff",
    dic_path: str = "custom.dic",
    words_file: str = "words.txt"
):
    aff_path = Path(aff_path)
    dic_path = Path(dic_path)
    words_path = Path(words_file)

    # Чтение и вывод содержимого .aff
    print(".aff " + "-" * 50)
    print(aff_path.read_text(encoding="utf-8"))
    
    # Чтение и вывод содержимого .dic
    print(".dic" + " " + "-" * 50)
    print(dic_path.read_text(encoding="utf-8"))
    print("-" * 55)

    checker = hunspell.HunSpell(str(dic_path), str(aff_path))

    # Чтение слов для проверки
    words_to_check = words_path.read_text(encoding="utf-8").splitlines()
    words_to_check = [w.strip() for w in words_to_check if w.strip()]

    # Проверка каждого слова
    print("Проверка слов:")
    for word in words_to_check:
        is_correct = checker.spell(word)
        status = "✅" if is_correct else "❌"
        print(f"{word} — {status}")

    del checker

В каждом примере показано содержимое файлов aff и dic, а также несколько слов для проверки. В отдельных местах приведены цитаты из документации.

  • Минимальный словарь
  • Учёт регистра символов
  • KEEPCASE
  • Небуквенные символы
  • BREAK
  • IGNORE
  • ICONV
  • COMPOUNDFLAG
  • COMPOUNDMIN
  • ONLYINCOMPOUND
  • COMPOUNDRULE

Минимальный словарь

Файл .aff обязательно должен содержать указание кодировки. Лучше использовать UTF-8. Если других правил в .aff нет, слова из .dic будут проверяться на точное совпадение.

.aff --------------------------------------------------
SET UTF-8
.dic --------------------------------------------------
1
сюртук
-------------------------------------------------------
Проверка слов:
сюртук — ✅
сюртуки — ❌
холст — ❌

SET кодировка

Устанавливает кодировку символов для слов и морфем в файлах словаря и аффиксов. Поддерживаемые значения: UTF-8, ISO8859−1–ISO8859−10, ISO8859−13–ISO8859−15, KOI8-R, KOI8-U, microsoft-cp1251, ISCII-DEVANAGARI.

В большинстве словарей используется кодировка UTF-8. Примеры словарей с другой кодировкой: de_DE_frami и pl_PL.dic.

Учёт регистра символов

Если слово в словаре указано строчными буквами, оно будет считаться правильным даже при написании с заглавной буквы. Если же слово начинается с прописной, оно будет правильным только при таком же написании. Любое слово, написанное полностью заглавными буквами, будет признано корректным.

Эта особенность используется для проверки имён собственных.

.aff --------------------------------------------------
SET UTF-8
.dic --------------------------------------------------
2
сюртук
Василий
-------------------------------------------------------
Проверка слов:
сюртук — ✅
Сюртук — ✅
СЮРТУК — ✅
сЮртук — ❌
Василий — ✅
ВАСИЛИЙ — ✅
василий — ❌
вАсилий — ❌

KEEPCASE

Чтобы задать особое поведение для конкретных слов, в .aff-файле объявляются специальные флаги, которые затем применяются к словам в .dic через символ /.

В следующем примере директива KEEPCASE объявляет флаг K, который затем добавляется к двум словам в .dic.

.aff --------------------------------------------------
SET UTF-8
KEEPCASE K
.dic --------------------------------------------------
2
сюртук/K
iPhone/K
-------------------------------------------------------
Проверка слов:
сюртук — ✅
Сюртук — ❌
СЮРТУК — ❌
iPhone — ✅
IPHONE — ❌
iphone — ❌
iPhOne — ❌

KEEPCASE флаг

Для слов, отмеченных флагом KEEPCASE, запрещается образование форм в верхнем регистре и форм, начинающихся с прописной буквы. Полезно для специальных орфографий (в которых единицы измерений и символы валют не изменяют регистр даже в текстах, состоящих из прописных букв) и систем написания (например, для сохранения нижнего регистра символов IPA).

Команда используется в словарях de_DE_frami и fr.

Небуквенные символы

В словах могут встречаться небуквенные символы: апостроф (’), дефис (-), цифры и другие. С их помощью в словарь можно добавлять составные слова и сокращения.

.aff --------------------------------------------------
SET UTF-8
.dic --------------------------------------------------
5
абстрактно-общее
Д’Аржансон
Д.
м.
Agent007
-------------------------------------------------------
Проверка слов:
абстрактно-общее — ✅
Д’Аржансон — ✅
Д'Аржансон — ❌
Д. — ✅
Д — ❌
М. — ✅
Agent007 — ✅

Слова в словаре могут содержать символ /, но его нужно экранировать, так как он служит разделителем между словом и флагами.

.aff --------------------------------------------------
SET UTF-8
.dic --------------------------------------------------
1
и\/или
-------------------------------------------------------
Проверка слов:
и/или — ✅

Файл словаря (.dic) содержит список слов, по одному слову в строке. В первой строке словарей (за исключением персональных словарей) указывается приблизительное количество слов в словаре (для оптимального распределения памяти). После каждого слова может следовать слэш ("/") и один или более флагов, соответствующих аффиксам и атрибутам. Слова в словаре также могут содержать слэши, экранированные "\/". По умолчанию, флаг представляет собой один (обычно, алфавитный) символ. В файле словаря Hunspell также может существовать поле для морфологического описания, отделяемое табуляцией.

BREAK

Hunspell умеет проверять составные слова, образованные из простых. В русском языке такие слова могут соединяться через дефис (-) или косую черту (/). Проверим, как это работает.

.aff --------------------------------------------------
SET UTF-8
.dic --------------------------------------------------
5
и
или
либо
абстрактно
общее
-------------------------------------------------------
Проверка слов:
и/или — ❌
либо/либо — ❌
абстрактно-общее — ✅
конкретно-общее — ❌

Дефис работает, а косая черта — нет. Список символов-разделителей можно задать с помощью команды BREAK.

BREAK количество_определений_разделений BREAK символ_или_последовательность_символов

Определяет точку для разделения слова и проверку полученных частей по отдельности. Полезно для сложносоставных слов, объединенных с помощью одного символа или последовательности символов (например, дефис в английском и немецком или дефис и короткое тире в венгерском языках). Тире не рекомендуется использовать как точку для разбиения слов, т.к. сложносоставные слова с тире могут содержать неправильные части. Используя BREAK, Hunspell может проверить обе части сложносоставных слов, разделяя слова по обычным и коротким тире:

.aff --------------------------------------------------
SET UTF-8

BREAK 2
BREAK /
BREAK -
.dic --------------------------------------------------
5
и
или
либо
абстрактно
общее
-------------------------------------------------------
Проверка слов:
и/или — ✅
либо/либо — ✅
абстрактно-общее — ✅
конкретно-общее — ❌

Команда используется в словарях de_DE_frami, fr, grc_GR.

IGNORE

Иногда полезно исключить из проверки определённые символы. Рассмотрим пример: в словаре есть несколько слов, некоторые из которых указаны с ударением.

.aff --------------------------------------------------
SET UTF-8
.dic --------------------------------------------------
3
большим
что́
что
-------------------------------------------------------
Проверка слов:
большим — ✅
бо́льшим — ❌
что́ — ✅
что — ✅

Слова с ударением проверяются корректно. Слово бо́льшим определяется как ошибочное, потому что в словаре нет его версии с ударением. Удобно игнорировать символ ударения при проверке, чтобы не дублировать все слова.

.aff --------------------------------------------------
SET UTF-8

IGNORE ́
.dic --------------------------------------------------
2
большим
что
-------------------------------------------------------
Проверка слов:
большим — ✅
бо́льшим — ✅
что́ — ✅
что — ✅

Символ ударения игнорируется (удаляется) при проверке, поэтому как слова с ударением, так и без него, распознаются как правильные.

Команда используется в словаре uk_UA.

ICONV

Команда ICONV определяет замены во входных данных перед проверкой по словарю. Например, в тексте может использоваться неправильный апостроф (') вместо правильного (’). В таком случае слово будет признано ошибочным.

.aff --------------------------------------------------
SET UTF-8
.dic --------------------------------------------------
1
Д’Аржансон
-------------------------------------------------------
Проверка слов:
Д'Аржансон — ❌

При замене символа ' на ’ с помощью ICONV слово определяется верно.

.aff --------------------------------------------------
SET UTF-8

ICONV 1
ICONV ' ’
.dic --------------------------------------------------
1
Д’Аржансон
-------------------------------------------------------
Проверка слов:
Д'Аржансон — ✅

Однако в данном случае замена апострофа может быть не самой удачной стратегией — она скрывает ошибочное использование символа.

Команда используется в словаре uk_UA. Там она применяется особым образом: в качестве символа замены указан 0, что означает удаление. Из-за этого словарь игнорирует некоторые символы, что может приводить к ложному признанию слов правильными. Эта особенность может влиять на системы, использующие несколько словарей разных языков.

.aff --------------------------------------------------
SET UTF-8

ICONV 6
ICONV a 0
ICONV b 0
ICONV c 0
ICONV d 0
ICONV e 0
ICONV f 0
.dic --------------------------------------------------
1
холст
-------------------------------------------------------
Проверка слов:
bbbхолст — ❌
aba — ✅
abaz — ❌

COMPOUNDFLAG

Hunspell позволяет создавать правила формирования составных слов из базовых. Это сложный функционал, реализованный набором директив. Директива COMPOUNDFLAG объявляет флаг, помеченные которым слова могут входить в составные слова в любом порядке.

.aff --------------------------------------------------
SET UTF-8

COMPOUNDFLAG C
.dic --------------------------------------------------
3
само/C	
кат/C
лёт
-------------------------------------------------------
Проверка слов:
само — ✅
лёт — ✅
кат — ✅
самокат — ✅
самолёт — ❌
катсамо — ✅

COMPOUNDFLAG флаг

Слова, отмеченные COMPOUNDFLAG, могут являться частью составного слова (за исключением случаев, когда слово имеет длину меньшую, чем указано в COMPOUNDMIN). Аффиксы с COMPOUNDFLAG также допускают использование слов с ними в составе сложных слов.

COMPOUNDMIN

Директива COMPOUNDMIN задаёт минимальную длину слов, которые могут быть частями составного слова. По умолчанию — 3 символа. Даже если слово помечено COMPOUNDFLAG, оно не будет использоваться как составная часть, если короче COMPOUNDMIN. В примере ниже слово кат не становится составной частью, поэтому самокат определяется как ошибка.

.aff --------------------------------------------------
SET UTF-8

COMPOUNDFLAG C
COMPOUNDMIN 4
.dic --------------------------------------------------
4
само/C	
кат/C
водо/C
канал/C
-------------------------------------------------------
Проверка слов:
само — ✅
кат — ✅
самокат — ❌
водо — ✅
канал — ✅
водоканал — ✅

Команда используется в словарях de_DE_frami.dic и en_US.dic.

ONLYINCOMPOUND

ONLYINCOMPOUND флаг

Суффиксы, отмеченные ONLYINCOMPOUND, могут находиться только в составных словах (словосоединяющие морфемы в немецком и шведском языках). Флагом ONLYINCOMPOUND также можно отметить обычные слова (см. примеры в tests/onlyincompound.*).

Чтобы слово использовалось только внутри составных слов, оно должно быть помечено и ONLYINCOMPOUND, и COMPOUNDFLAG.

.aff --------------------------------------------------
SET UTF-8

COMPOUNDFLAG C
ONLYINCOMPOUND O
.dic --------------------------------------------------
4
само/C	
кат/C
водо/CO
канал/C
-------------------------------------------------------
Проверка слов:
само — ✅
кат — ✅
самокат — ✅
водо — ❌
канал — ✅
водоканал — ✅
водокат — ✅

Команда используется в словарях de_DE_frami.dic и en_US.dic.

COMPOUNDRULE

Директива COMPOUNDRULE задаёт правила построения составных слов. Например, можно указать, что одни части могут стоять только в начале, другие — только в конце. Правила COMPOUNDRULE работают с флагами, объявленными другими директивами: COMPOUNDFLAG, COMPOUNDBEGIN, COMPOUNDLAST и другими.

COMPOUNDBEGIN и COMPOUNDLAST не работают без COMPOUNDRULE. Способ соединения определяется в правилах COMPOUNDRULE, поэтому названия COMPOUNDBEGIN и COMPOUNDLAST нужны в первую очередь для читаемости — их можно использовать условно.

COMPOUNDBEGIN флаг

Слова, отмеченные COMPOUNDBEGIN (или с отмеченным аффиксом), могут быть первыми элементами составных слов.

COMPOUNDLAST флаг

Слова, отмеченные COMPOUNDLAST (или с отмеченным аффиксом), могут быть последними элементами составных слов.

.aff --------------------------------------------------
SET UTF-8

ONLYINCOMPOUND O
COMPOUNDBEGIN B
COMPOUNDLAST L

COMPOUNDRULE 1
COMPOUNDRULE BL
.dic --------------------------------------------------
4
само/B
кат/L
водо/BO
канал/L
-------------------------------------------------------
Проверка слов:
само — ✅
кат — ✅
самокат — ✅
водо — ❌
канал — ✅
водоканал — ✅
каналводо — ❌
водокат — ✅
катводо — ❌

Команды используются в словарях de_DE_frami.dic и en_US.dic.

Последниее изменение: 06.09.2025, 08:55