Пользователь
0,0
рейтинг
13 ноября 2012 в 13:20

Разработка → Многоязыковая проверка орфографии для программ, использующих Hunspell из песочницы

Многие часто сталкиваются с необходимостью проверки орфографии на нескольких языках одновременно, однако далеко не все существующие программы позволяют производить такую проверку, предлагая пользователю переключаться с одного языка на другой, что довольно неудобно и отнимает массу времени.

Не желая мириться с подобным неудобством для программ, использующих Hunspell словари (FireFox, Seamonkey, Miranda и др.) было принято решение создать автоматическую графическую утилиту для склейки нескольких языков, с возможностью дальнейшего использования полученных словарей.


История создания

Пару строк об истории создания. Идея зародилась еще в 2008 году, когда мной был скомпилирован комплексный Русско–Английский словарик для FireFox.

Он был размещен на ftp сайте Mozilla.
ftp.mozilla-russia.org/dictionaries/ru-en_spell_dictionary.xpi
Так же была тема на форуме.
forum.mozilla-russia.org/viewtopic.php?id=15316

С того момента прошло немало времени, но буквально недавно я почти одновременно получил несколько писем от интересующихся людей, которые просили дать что-то более свежее.
Нежели рассылать готовые обновления я решил доработать GUI утилиту, которая позволила бы пользователям самостоятельно собрать несколько словарей воедино.

В тот момент утилита была написана «для себя» на Delphi, который использовался мной на работе, однако назвать это кроссплатформенным решением нельзя.
Конечно, сейчас можно использовать последние версии Embarcadero RAD Studio для создания кроссплатформенных решений, тем не менее я решил остановиться на реализации автоматической утилиты средствами Java.

Задача

Утилита в минимальной её реализации должна уметь

1. Загружать словари из следующих наиболее распространенных форматов
— несжатый вид *.dic и *.aff
— ZIP архив (*.zip)
— XPInstall формат (*.xpi)
— Расширения OpenOffice (*.oxt)

2. Давать возможность выбора словарей для склейки

3. Давать возможность изменения имени полученных словарей и описания

4. Выгружать в форматах
— несжатый вид *.dic и *.aff
— ZIP архив (*.zip)
— XPInstall формат (*.xpi)

Реализация

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

Информацию по Hunspell можно найти тут
hunspell.sourceforge.net

Описание формата
pwet.fr/man/linux/fichiers_speciaux/hunspell
или в русском переводе
mozilla-russia.org/projects/dictionary/hunspell.html

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

Учитывая формат и структуру файлов основная задача состояла в том, чтобы помимо простой склейки файлов словарей не нарушить соответствие аффиксов для разных словарей.

Для именования флагов в файле аффиксов существует три подхода
1. По умолчанию – каждый аффикс именуется одной буквой (с учетом реестра) или цифрой.
2. Long — каждый аффикс именуется двумя буквами или буквой с цифрой.
3. Number – каждый аффикс имеет значение от 1 до 65000.

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

Так же все файлы словарей часто были в разных кодировках, поэтому для унификации был выбрана общая результирующая кодировка UTF-8.

В остальном особых обозримых проблем не было.
Программа загружает словари, склеивает их, игнорируя дубликаты слов, в результате отбрасывает неиспользованные флаги аффиксов.

В рамках данной статьи я не буду вдаваться в реализацию отдельных процедур, поскольку для желающих я разместил исходный код тут.
Там так же есть скрипт для ANT сборщика.

code.google.com/p/hunspell-merge

Как работать

На текущий момент я протестировал работу утилиты под Ubuntu и ОС Windows 7 с указанными в задаче на реализацию типами исходных файлов.
Для работы требуется Java Runtime (JRE).

Качаем с этой странички HunspellMerge.jar и файл запуска для вашей ОС Linux или Windows. Для Linux не забываем проставить права на запуск файла.
Так же возможен запуск с использованием Java Webstart — файл запуска находится по этой ссылке.





Для работы требуется иметь набор исходных файлов, которые по умолчанию могут быть размещены в подпапке dictionaries рабочей папки утилиты.

Дополнительные словари можно скачать по ссылкам размещенным тут
code.google.com/p/hunspell-merge/wiki/OnlineDictionaries

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

Использование результатов работы

FireFox
Формат вывода (XPInstall)
Просто копируем путь файла или перетягиваем файл в адресную строку браузера.
Нажимаем ввод и устанавливаем расширение.

Miranda / MirandaNG
Формат вывода (Dictionary)
Копируем файлы (*.aff, *.dic) в папку Dictionaries в каталоге с программой. Перезапускаем Miranda.

Планы

Поскольку утилита была написана за пару-тройку вечеров, то особого времени уделить тестированию и поддержке расширенных инструкций файла аффиксов не было. Это есть в планах на доработку, однако, некоторые инструкции для одного языка могут идти в разрез с такими же инструкциями для другого, поэтому пока поддерживается три типа основных флагов – суффиксы (SFX), префиксы (PFX), замена (REP).

Добавить русский язык для интерфейса.

Так же неплохо было бы написать документацию и облагородить страничку на GoogleCode.

Заключение

Очень хотелось бы услышать в каких еще программах работают подобные склеенные словари.
Осознаю, что программа не лишена недостатков, поэтому буду рад услышать пожелания и предложения по усовершенствованию утилиты.

Спасибо за интерес.

UPD Как выяснилось есть польза даже от простой склейки словарей одного языка, загруженных, с разных ресурсов или имеющих разное направление, например, технические, экономические.
@SergioBarbery
карма
–1,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (33)

  • 0
    А можно результат склеивания в aff и dic форматах?
    Насколько я понимаю это панацея для, исторически кривого, спелчеккера OSX!
    Скрин

    • 0
      Результат склеивания нужен просто так для проверки или нужен для конкретных языков?
      Дело в том, что если программа использующая Hunspell словари позволяет своими средствами проверять на нескольких языках одновременно, то утилита вовсе не требуется.
      • +1
        1. В osx оооочень кривой русский словарь, настолько, что в нем находили орфографические ошибки.
        2. Штатный словарь очень маленький.
        3. Мультиподдержка есть, но лучше-бы ее не было:



        4. Прошу хороший смешанный словарь русско-английских слов.
        5. Заодно потестить как один словарь работает для 2х языков в OSX.
        • +2
          Слил 5 русских и 4 английских словаря, взятых из OpenOffice и Mozilla расширений, воедино.
          Вот что вышло (*.aff и *.dic) в zip архиве.
          sendfile.su/708140
          Жду результата, у меня к сожалению проверить на MacOS пока нет.
          • 0
            По-моему — шикарно! Огромное спасибо.

            Результат
            Текст в Mail.app:


            Тащим вверх и включаем только синтезированный словарь:


            Убираем кривое автоопределение языков указав конкретный словарь:


            • 0
              Не думал, но наверное можно одним из полезных применений сделать не только многоязыковую проверку, но и расширение словарей для одного языка.
  • 0
    Попробовал склеить по максимуму английские и русские словари по ссылкам, программа обрывала работу с сообщением о нехватке памяти. Исключил явные дубликаты и словари с разницей в несколько десятков слов, всё равно не получается.

    Стал соединять постепенно. Сначала весь американский английский, потом британский, потом оба варианта. Русский с «е», русский с «ё», русский с «её». Потом соединил «е» и «ё». Но при попытке соединить этот гибрид с изначальными гибридами «её» — опять нехватка памяти (два файла в UTF-8 по 13 и 11 мегабайт каждый).

    Windows XP, Java 7.0.90.5. Сообщение в консоли начинается с:

    j:\temp\HunspellMerge>java -cp HunspellMerge.jar hunspell.merge.HunspellMerge
    Exception in thread «AWT-EventQueue-0» java.lang.OutOfMemoryError: Java heap spa
    ce

    потом идёт длинный список файлов. Свободной памяти в это время ещё мегабайтов семьсот. Ко времени сбоя уже есть папка output с файлом аффиксов.
    • +1
      Сколько оперативки в наличии? И еще — можно ссылки на использованные словари?
      • 0
        Простите, промахнулся, чуть ниже ответил.
        • 0
          Понятно. Я уже вижу пути оптимизации использования памяти. На днях реализую.

          Пока что могу предложить попробовать увеличить размер Java heap при запуске утилиты.
          Добавить ключи в строку запуска Java

          -Xms<size>set initial Java heap size
          -Xmx<size> set maximum Java heap size

          Например:

          java -Xmx1024m -cp HunspellMerge.jar hunspell.merge.HunspellMerge

          Вот здесь на всякий случай есть информация по проблемам при установке установке Java Heap
          • 0
            Да, с таким ключом соединяется, спасибо.

            Но, к сожалению, есть другая проблема. Словарь аффиксов почему-то от соединения к соединению иногда существенно уменьшается.

            Конечный словарь для английского вышел всего на 543 байта, тогда как исходные достигали десятков килобайт.

            Конечный для русского вышел на 38 килобайт, раз в десять меньше некоторых исходных.

            Когда я объединил русский словарь аффиксов с английским, получилось всего семь килобайт. После установки такой словарь начинает помечать как ошибки множество правильных русских словоформ, которые обычный словарь в Firefox не помечает.
            • +1
              Спасибо за информацию.
              Нужно будет посмотреть, возможно тут дело в порядке соединения словарей и алгоритме игнорирования дубликатов слов. Я буду изучать. Как будут результаты — я отпишу тут.
            • 0
              Доработал утилиту (v.1.1).
              Добавлено окно лога, чтобы не было скучно ждать, улучшено соединение аффиксов.
              code.google.com/p/hunspell-merge/downloads/

              Можно пробовать.
              • 0
                Попробовал объединить словари британского английского для начала.

                Лог:
                Loading: british_english_dictionary_updated-1.19.3-fx+sm+tb.xpi / en-GB (ISO-8859-1)…
                Merging 0 affixes…
                Merging 46280 words…
                Done!

                Loading: en_GB-oed.zip / en_GB-oed (ISO-8859-1)…
                Merging 0 affixes…
                Merging 46113 words…
                Done!

                Loading: en_GB-pack.zip / en_GB (ISO-8859-1)…
                Merging 0 affixes…
                Merging 46146 words…
                Done!

                Loading: en_GB_oxt.zip / en_GB (UTF-8)…
                Merging 0 affixes…
                Merging 56506 words…
                Done!

                Checking unused affixes…
                Saving affix file: en_gb.aff
                Saving dictionary file: en_gb.aff

                Result 0 affixes, 65733 words
                Work time (min:sec) = 00:02
                Output folder: j:\temp\HunspellMerge\output\


                На выходе файл аффиксов из трёх строчек:

                SET UTF-8
                TRY
                FLAG NUMBER
                • 0
                  Словари иногда не содержат файла аффиксов. В английских словарях это часто встречается.
                  Приложите прямые ссылки на исходные словари — тогда я смогу посмотреть в чем причина.
                • 0
                  Еще бывает, что файл аффиксов не содержит никаких аффиксов, а только указывает на кодировку словаря.
                  Это не является нарушением формата словарей.
                  • 0
                    Вот архив с четырьмя словарями.

                    Там во всех четырёх большие файлы аффиксов.
                    • 0
                      Да, это был баг. Исправил. Взять можно там же (v.1.2).
                      Поправил. Еще нужно будет поработать над дополнительными типами аффиксов, встречающимися в этих словарях.
                      • 0
                        Да, похоже, ещё можно дорабатывать. Попробовал опять пройтись в таком порядке:

                        en-gb
                        en-us
                        en-gb-us

                        ru-yo
                        ru-ie
                        ru-yoie
                        ru-yoie-yo-ie

                        ru-en

                        Иногда аффиксы нормально соединяются (результирующее число чуть меньше суммы), но иногда опять происходит разительное сокращение (вроде 250+44=18). На этапе ru-yoie-yo-ie программа зависла, через минут пять максимальной нагрузки процессора пришлось её насильно выключать.

                        Вот с этим набором словарей я работал (некоторые oxt я раздербанил, чтобы выбрать только нужные варианты английского). Может, пригодится, если вы пройдётесь в том же порядке соединения.
                        • 0
                          Изменил алгоритм обработки аффиксов (v.1.3). Возможно пока будет некоторое количество излишней информации. Я думаю над возможностями «безвредного» удаления дубликатов.
                          Находится где обычно.
                          Если будут проблемы — можно в личку или на почту (там в проекте на гуглокоде есть она), чтобы тут не разводить диспуты.
                          • 0
                            Спасибо. Проверю попозже и напишу. Лучше, конечно, излишняя информация, чем потери.
                          • 0
                            Всё ещё проблемы с аффиксами.

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

                            Лог 1
                            Loading: en_gb.dic / en_gb (UTF-8)…
                            Merging 326 affixes…
                            Merging 60590 words…
                            Done!

                            Loading: en_us.dic / en_us (UTF-8)…
                            Merging 171 affixes…
                            Merging 70372 words…
                            Done!

                            Checking unused affixes…
                            Saving affix file: en_gb_us.aff
                            Saving dictionary file: en_gb_us.aff

                            Result 20 affixes, 82834 words
                            Work time (min:sec) = 00:14
                            Output folder: j:\temp\HunspellMerge\output\


                            Лог 2
                            Loading: ru_ie.dic / ru_ie (UTF-8)…
                            Merging 258 affixes…
                            Merging 476711 words…
                            Done!

                            Loading: ru_yo.dic / ru_yo (UTF-8)…
                            Merging 74 affixes…
                            Merging 153255 words…
                            Done!

                            Checking unused affixes…
                            Saving affix file: ru_ie_yo.aff
                            Saving dictionary file: ru_ie_yo.aff

                            Result 18 affixes, 490665 words
                            Work time (min:sec) = 00:47
                            Output folder: j:\temp\HunspellMerge\output\


                            Лог 3
                            Loading: ru_ieyo.dic / ru_ieyo (UTF-8)…
                            Merging 375 affixes…
                            Merging 637637 words…
                            Done!

                            Loading: ru_ie_yo.dic / ru_ie_yo (UTF-8)…
                            Merging 18 affixes…
                            Merging 490665 words…
                            Done!

                            Checking unused affixes…
                            Saving affix file: ru_ieyo_ie_yo.aff
                            Saving dictionary file: ru_ieyo_ie_yo.aff

                            Result 19 affixes, 720552 words
                            Work time (min:sec) = 01:07
                            Output folder: j:\temp\HunspellMerge\output\


                            Лог 4
                            Loading: en_gb_us.dic / en_gb_us (UTF-8)…
                            Merging 20 affixes…
                            Merging 82834 words…
                            Done!

                            Loading: ru_ieyo_ie_yo.dic / ru_ieyo_ie_yo (UTF-8)…
                            Merging 19 affixes…
                            Merging 720552 words…
                            Done!

                            Checking unused affixes…
                            Saving affix file: en_gb_us_ru_ieyo.aff
                            Saving dictionary file: en_gb_us_ru_ieyo.aff

                            Result 20 affixes, 803386 words
                            Work time (min:sec) = 00:21
                            Output folder: j:\temp\HunspellMerge\output\


                            И даже при обёртывании одного словаря в xpi происходит странное:

                            Лог 5
                            Loading: en_gb_us_ru_ieyo.dic / en_gb_us_ru_ieyo (UTF-8)…
                            Merging 20 affixes…
                            Merging 803386 words…
                            Done!

                            Checking unused affixes…
                            Saving affix file: en_gb_us_ru_ieyo.aff
                            Saving dictionary file: en_gb_us_ru_ieyo.aff
                            Create XPI: en-gb-us-ru-ieyo.xpi

                            Result 11 affixes, 803386 words
                            Work time (min:sec) = 00:30
                            Output folder: j:\temp\HunspellMerge\output\

                          • 0
                            Странно. Попробовал без промежуточных словарей, всё вроде бы получается хорошо:

                            Лог для 14-ти словарей сразу
                            Loading: addon-0.4.4.1-sm+tb+fx+fn.xpi / ru (KOI8-R)…
                            Merging 25 affixes…
                            Merging 146270 words…
                            Done!

                            Loading: british_english_dictionary_updated-1.19.3-fx+sm+tb.xpi / en-GB (ISO-8859-1)…
                            Merging 63 affixes…
                            Merging 46280 words…
                            Done!

                            Loading: dict_ru_RU-0.3.7.oxt / hyph_ru_RU (KOI8-R)…
                            Merging 25 affixes…
                            Merging 3875 words…
                            Done!

                            Loading: dict_ru_RU-AOT-0.2.7-ieyo.oxt / russian-aot-ieyo (KOI8-R)…
                            Merging 364 affixes…
                            Merging 379323 words…
                            Done!

                            Loading: dict_ru_RU-rk-ieyo-0.4.2.oxt / russian-rk-ieyo (KOI8-R)…
                            Merging 11 affixes…
                            Merging 322129 words…
                            Done!

                            Loading: en_GB-oed.zip / en_GB-oed (ISO-8859-1)…
                            Merging 63 affixes…
                            Merging 46113 words…
                            Done!

                            Loading: en_GB-pack.zip / en_GB (ISO-8859-1)…
                            Merging 61 affixes…
                            Merging 46146 words…
                            Done!

                            Loading: en_GB_oxt.zip / en_GB (UTF-8)…
                            Merging 712 aliases…
                            Merging 150 affixes (712 aliases)…
                            Merging 56506 words…
                            Done!

                            Loading: en_US_oxt.zip / en_US (UTF-8)…
                            Merging 589 aliases…
                            Merging 152 affixes (589 aliases)…
                            Merging 52890 words…
                            Done!

                            Loading: russian_hunspell_dictionary-1.0.20120501-sm+fn+fx+tb.xpi / ru_RU (UTF-8)…
                            Merging 236 affixes…
                            Merging 174304 words…
                            Done!

                            Loading: ru_RU.zip / ru_RU (KOI8-R)…
                            Merging 24 affixes…
                            Merging 128905 words…
                            Done!

                            Loading: ru_RU_ye.zip / ru_RU_ie (KOI8-R)…
                            Merging 11 affixes…
                            Merging 321998 words…
                            Done!

                            Loading: ru_RU_yo.zip / ru_RU_yo (KOI8-R)…
                            Merging 24 affixes…
                            Merging 129167 words…
                            Done!

                            Loading: united_states_english_spellchecker-6.0-fx+sm+tb.xpi / en-US (ISO-8859-1)…
                            Merging 24 affixes…
                            Merging 62119 words…
                            Done!

                            Checking unused affixes…
                            Saving affix file: en_ru.aff
                            Saving dictionary file: en_ru.aff
                            Create XPI: en-ru.xpi

                            Result 1213 affixes, 803396 words
                            Work time (min:sec) = 00:56
                            Output folder: j:\temp\HunspellMerge\output\


                            Спасибо. Погоняю немного этот словарь, если будут проблемы, напишу.
                            • +1
                              Исправил загрузку промежуточных словарей (v.1.4).
                              + Добавил отображения количества слов в списке словарей.
                              Однако, как показала практика, если увлекаться слиянием сильно большого количества разных словарей, особенно если они неизвестного качества, то результат получается, прямо скажу, не очень.
                              • 0
                                Спасибо.
                                Да, доверие источнику словаря тут много значит.
  • 0
    По всем вашим трём ссылкам все русские и все английские (только американский и британский английский) словари. Но для проверки можно только русскими ограничится, потому что уже с ними проблема.

    Оперативки — восемь гигов, но система видит только три с хвостиком, в остальном рамдиск. Во время соединения свободно ещё мегабайт семьсот. В программе мониторинга ресурсов никакого скачка потребления памяти в момент сбоя не заметно.
  • 0
    у меня в убунте большинство программ поддерживают hunspell с двуязычным словарём. Про то, как этого добиться, я даже пост написал: двуязычная русско-английская проверка правописания в ubuntu
    • 0
      Это хорошо. Тем не менее область применения для утилиты все равно пока остается, хотя бы для Windows.
  • 0
    TortoiseGIT и TortoiseSVN проверяют орфографию в log message при коммите всеми словарями из C:\Program Files\TortoiseGit\Languages одновременно
    • 0
      Было бы замечательно если бы все программы так умели. Как я и сказал — в основном сделано от безысходности. Когда все будут уметь проверять одновременно всеми словарями — со спокойным сердцем похороню утилиту.
  • 0
    Отлично, то, что я искал. Спасибо.
    Использую в Windows для Firefox, Thundebrird, Skype и Emacs.
    • 0
      … и так же Miranda IM.
    • 0
      Сегодня были внесены некоторые изменения, связанные со склейкой. Можно попробовать обновление.
      На всякий случай завел лог изменений.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.