Структура словарей 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
, а также несколько слов для проверки. В отдельных местах приведены цитаты из документации.
Минимальный словарь
Файл .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
.