Склонение по падежам на C#
Morpher.dll – это .NET-библиотека, реализующая функции склонения по падежам, автоматического определения рода словосочетания и
прописи чисел на русском языке.
Данная страница посвящена в основном технической стороне использования библиотеки;
лингвистическая сторона вопроса раскрыта на странице Описание технологии склонения.
Реализованные функции
Весь API библиотеки можно представить следующим кодом:
namespace Slepov.Russian.Morpher
{
public class Склонятель
{
public Склонятель (string key, TextReader userDict = null);
public IСклоняемое Проанализировать (
string словосочетание,
params Признак [] признаки);
public string Пропись (int n, ref string unit,
Падеж падеж = Падеж.Именительный);
}
}
Технические характеристики
-
Поддерживаемые платформы:
.NET Framework 2.0 и выше,
.NET Standard 2.0 и выше (включая .NET Core 2.0 и выше).
-
Операционные системы: MacOS, Linux, Windows.
-
Код библиотеки написан полностью на C# и скомпилирован для платформы MSIL (AnyCPU).
- Библиотека не имеет никаких внешних зависимостей,
не имеет интерфейса пользователя и не требует прав доступа ни к диску, ни к сети.
- Все public методы библиотеки потокобезопасны, что особенно актуально при её использовании
в серверных приложениях. Потокобезопасность достигается без использования блокировок.
Комплект поставки
Модуль поставляется в виде одного файла Morpher.Russian.2.15.0.nupkg,
который представляет собой архив и содержит следующие файлы:
| Morpher.dll |
~400K |
Сама библиотека. |
| Morpher.xml |
~10K |
Файл XML-комментариев для отображения подсказок в Visual Studio. |
Инструкция по установке
Поместите дистрибутив Morpher.Russian.x.x.x.nupkg в папку по вашему выбору.
В Visual Studio выберите проект, в который нужно добавить библиотеку,
нажмите правой кнопкой мыши на узел Dependencies и
выберите пункт меню Manage NuGet Packages...
Нажмите на значок в виде шестеренки рядом с Package source:
В открывшемся списке источников пакетов добавьте вашу папку в качестве нового источника:
-
Нажмите значок + в правом верхнем углу.
-
В качестве имени (Name) укажите, например, Morpher.
-
В графе Source укажите путь к папке, где лежит nupkg.
-
Нажмите Update.
-
Нажмите ОК.
-
Рядом с Package source выберите наш новый источник Morpher.
-
Перейдите на вкладку Browse. В списке должен появиться пакет Morpher.Russian.
-
Нажмите кнопку Install.
-
Если появится окно Preview Changes, нажмите кнопку Apply.
-
Если появится окно License Acceptance, нажмите кнопку I Accept.
После завершения установки пакета добавьте в редактор следующий код:
using Slepov.Russian.Morpher;
var склонятель = new Склонятель("лицензионный ключ");
var проверка = склонятель.Проанализировать("проверка");
System.Console.WriteLine(проверка.Винительный);
Если код запускается и выдает «проверку», то установка прошла успешно.
Функция склонения по падежам и числам
public IСклоняемое Проанализировать (string словосочетание, params Признак [] признаки);
Параметры:
словосочетание – слово или словосочетание для склонения. Должно быть на русском языке, иначе функция выдает null.
признаки сообщают функции дополнительную информацию о склоняемом словосочетании: какого оно рода и к какой категории относится.
Признаки указывать необязательно, но в некоторых случаях их указание помогает снять неоднозначность, которая иначе привела бы к неправильному склонению.
public enum Признак
{
ФИО,
Нарицательное,
МужскойРод,
ЖенскийРод,
Одушевлённое,
Неодушевлённое
}
Подробнее об использовании признаков
Возвращает IСклоняемое.
Использование функции склонения проще всего проиллюстрировать на примере.
Вот пример кода на C# для формирования текста, в котором одно и то же ФИО фигурирует в различных падежах:
class HelloIvanIvanych
{
static void Main ()
{
Склонятель склонятель = new Склонятель ();
IСклоняемое получатель = склонятель.Проанализировать ("Иванов Иван Иваныч");
string справка = @"
СПРАВКА
Выдана {0} в том, что
{1} была получена справка
в том, что {2} не нуждается
более в получении никаких справок.";
System.Console.WriteLine (
справка,
получатель.Дательный,
получатель.Творительный,
получатель.Именительный);
}
}
(Да, это C# – он допускает использование русских букв в именах переменных и классов.)
Программа выдает в консольное окно следующий текст:
СПРАВКА
Выдана Иванову Ивану Иванычу в том, что
Ивановым Иваном Иванычем была получена справка
в том, что Иванов Иван Иваныч не нуждается
более в получении никаких справок.
Склонение производится за три этапа:
- Создание экземпляра класса Склонятель.
- Вызов метода Проанализировать.
- Чтение одного из свойств интерфейса IСклоняемое
для получения формы нужного падежа.
Вы можете спросить, зачем такие сложности? Почему бы не сделать API в виде одной функции:
public static string Просклонять (string s, Падеж падеж);
Это сделано для повышения быстродействия.
Первый этап – создание экземпляра класса Склонятель –
включает в себя загрузку словаря в память и занимает 100-200 миллисекунд.
Вроде бы немного, но помещать эту операцию в цикл не стоит.
Второй этап – анализ – относительно сложный процесс, который включает в себя поиск по словарю и анализ синтаксической структуры словосочетания.
Результат этого анализа, объект IСклоняемое, используется на третьем, последнем, этапе для генерации форм различных падежей единственного и множественного числа.
Если необходимо генерировать несколько падежных форм, как в примере выше, то время экономится, т.к. анализ проводится всего один раз.
Знание этих особенностей позволяет сделать программу молниеносной.
Приведу пример. Для контроля качества склонения используется база тестов,
где каждый тест состоит из трех частей:
- пример словосочетания в именительном падеже
- идентификатор падежа
- «правильный ответ» – как это словосочетание должно выглядеть в данном падеже.
Все тесты были составлены вручную. Я постоянно экспериментирую с алгоритмом склонения и каждый раз, внося изменения в программу,
прогоняю все тесты, чтобы быть уверенным, что качество склонения не ухудшилось.
На данный момент (1 сентября 2011 г.) объем базы составляет более 18 тысяч тестов.
Поэтому мне важно, чтобы тесты прогонялись как можно быстрее.
Теперь внимание, вопрос! Как вы думаете, сколько времени занимает прогон всех тестов?
Подсказка
Подсказка:
тестовая программа использует все 4 ядра моего ноутбука.
Ответ
Ответ:
628 миллисекунд.
Свойства интерфейса IСклоняемое
Объект IСклоняемое представляет собой совокупность форм одного числа (единственного или множественного).
| Название свойства |
Тип возвращаемого значения |
Описание |
| Именительный | string | Возвращает форму именительного падежа. |
| Родительный | string | Возвращает форму родительного падежа. |
| Дательный | string | Возвращает форму дательного падежа. |
| Винительный | string | Возвращает форму винительного падежа. |
| Творительный | string | Возвращает форму творительного падежа. |
| Предложный | string | Возвращает форму предложного падежа с предлогом О/ОБ/ОБО (о компьютере). |
| ПредложныйБезПредлога | string | Возвращает форму предложного падежа без предлога (компьютере). |
| Где | string | Возвращает форму, отвечающую на вопрос где? – в России, во Франции, в Крыму, на Канарах. Предлог выбирается автоматически. |
| Куда | string | Возвращает форму, отвечающую на вопрос куда? – в Россию, во Францию, в Крым, на Канары. Предлог выбирается автоматически. |
| Откуда | string | Возвращает форму, отвечающую на вопрос откуда? – из России, из Франции, из Крыма, с Канар. Предлог выбирается автоматически. |
| РодЧисло | РодЧисло | Возвращает род и число словосочетания в виде enum РодЧисло {ЕдинМуж, ЕдинЖен, ЕдинСред, Множ}. |
| Множественное | IСклоняемое | Возвращает объект IСклоняемое, представляющий набор форм множественного числа или null, если склоняемое уже во множественном числе. |
Определение рода и числа
Пример вызова:
switch (склонятель.Проанализировать("Чулпан").РодЧисло)
{
case РодЧисло.ЕдинМуж: return "мужской род";
case РодЧисло.ЕдинЖен: return "женский род";
case РодЧисло.ЕдинСред: return "средний род";
case РодЧисло.Множ: return "множественное число";
}
Идентификация фамилии, имени и отчества в строке
Эта функция позволяет выделить в строке имя, фамилию и отчество. Например:
[Test]
public void Александр_Сергеевич_Пушкин()
{
var склоняемое = склонятель.Проанализировать ("Александр Сергеевич Пушкин");
Assert.AreEqual ("Пушкин", склоняемое.ФИО.Фамилия);
Assert.AreEqual ("Александр", склоняемое.ФИО.Имя);
Assert.AreEqual ("Сергеевич", склоняемое.ФИО.Отчество);
}
Фамилия, имя и отчество могут располагаться в строке в любом (грамматически допустимом) порядке.
Отдельные компоненты ФИО могут отсутствовать, например:
| На входе |
Фамилия |
Имя |
Отчество |
| Александр Сергеевич |
|
Александр |
Сергеевич |
| Валентина Маркова |
Маркова |
Валентина |
|
| Михаил Богданович Барклай-де-Толли |
Барклай-де-Толли |
Михаил |
Богданович |
| АГАЕВ ФАРИД ЗАКИР ОГЛЫ |
АГАЕВ |
ФАРИД |
ЗАКИР ОГЛЫ |
В случае, если входная строка не распознана как ФИО, свойство ФИО будет равно
null.
Склонение прилагательных по родам
string ИзменитьРод (string прилагательное, РодЧисло родЧисло);
Функция принимает на вход полное прилагательное в форме именительного падежа мужского рода, а также род и число, в которые его необходимо поставить.
Вот пример функции, которая согласует прилагательное с существительным:
string Согласовать (string прилагательное, string существительное)
{
return склонятель.ИзменитьРод (прилагательное,
склонятель.Проанализировать (существительное).РодЧисло) + " " + существительное;
}
Для прилагательного острый и существительных нож, бритва, копье, ножницы
функция выдаст соответственно:
- острый нож
- острая бритва
- острое копье
- острые ножницы
Функция возвращает null, если:
- входная строка равна null;
- входная строка не может быть распознана как одно полное прилагательное или причастие
в форме мужского рода именительного падежа единственного числа.
Необходимо учитывать, что смысл прилагательного может меняться в зависимости от существительного. Так, острое зрение и острый вкус
не такие же острые, как острый нож.
Функция прописи чисел в заданном падеже
(Функции прописи дат и порядковых числительных («пятый этаж»)
поставляются отдельно.)
string Пропись (decimal n, ref string unit, Падеж падеж = Падеж.Именительный);
Возвращает пропись числа n (например, «сто двадцать пять» или «три целых две десятых»)
в указанном падеже
(онлайн-демо).
Если параметр unit не является словом или словосочетанием на русском языке
или слово не имеет нужной падежной формы,
то функция возвращает null.
Параметры:
n – число, пропись которого строится.
Есть также перегруженный вариант метода для типа int.
Функция работает для любых значений типов int
и decimal.
Для отрицательных значений пропись начинается со слова «минус».
Для 0.0 – «ноль».
unit – единица измерения – слово или словосочетание на русском языке
в именительном падеже единственного числа:
«рубль», «доллар США», «календарный день», «новое письмо» и т.п.
Если слово употребляется только во множественном числе, то
указывается форма именительного падежа множественного числа:
«сутки», «брюки», «ножницы».
При выходе из функции unit содержит единицу измерения в нужном падеже
(«рублей», «долларов США», «суток»).
Для этого указан модификатор ref.
падеж – при указании падежа пропись и единица измерения ставятся в заданный падеж.
Единица измерения (unit) склоняется в большинстве случаев, даже если указан именительный падеж,
как того требуют правила русского языка: «один рубль», «три рубля», «пять рублей», «пяти рублям», «пяти рублей» и т.п.
Функция возвращает пропись числа.
Пример 1. Сумма прописью
Существует множество вариантов написания «суммы прописью». Программист, приступающий к решению этой задачи, должен ответить для себя на множество вопросов:
- Названия денежных единиц писать полностью или сокращенно?
- Выводить копейки числом или прописью или и так, и так?
- Брать в скобки только пропись или все выражение, следующее за суммой цифрами?
- Писать пропись со строчной или заглавной буквы?
- Писать ли названия денежных единиц после всей суммы цифрами?
- Как отображать ноль копеек: 00, словом «ровно» или знаком =?
- Как отображать ноль рублей?
В результате число возможных вариантов может исчисляться сотнями. Вот неполный список примеров:
- 333,12 руб. (Триста тридцать три рубля 12 копеек)
- 333 р. 12 коп. (Триста тридцать три рубля 12 копеек)
- 333,12 (триста тридцать три рубля двенадцать копеек)
- 333,12 (триста тридцать три рубля 12 копеек)
- 333,12 (триста тридцать три) рубля 12 копеек
- 333 (триста тридцать три) руб. 12 коп.
- 333 (триста тридцать три) рубля 12 копеек
- 333 (триста тридцать три) рубля 12 (двенадцать) копеек
- 333,12 (триста тридцать три и 12/100) руб.
На практике выбор того или иного варианта прописи определяется видом документа, где она фигурирует, и нормами конкретного предприятия.
То есть проблема эта не лингвистическая, а бюрократическая.
Поэтому в библиотеке нет готовой функции формирования суммы прописью,
но ниже дан пример одного из возможных вариантов.
Морфер делает за вас трудную работу по склонению и формированию прописи отдельных чисел, а как расставлять скобки и точки – решать вам:
class ДенежнаяЕдиница
{
public string ПолноеНаименованиеЦелойЧасти {get; set;}
public string ПолноеНаименованиеДробнойЧасти {get; set;}
public string СокращенноеНаименованиеЦелойЧасти {get; set;}
public string СокращенноеНаименованиеДробнойЧасти {get; set;}
public string СуммаПрописью (decimal summa, Падеж падеж = Падеж.Именительный)
{
var sb = new StringBuilder ();
sb.Append (summa.ToString ("N2"));
sb.Append (' ');
sb.Append (СокращенноеНаименованиеЦелойЧасти);
sb.Append (' ');
sb.Append ('(');
int i = sb.Length; // запомнить позицию первой буквы прописи
sb.Append (Прописью (Math.Floor (summa), ПолноеНаименованиеЦелойЧасти, падеж));
sb.Append (' ');
sb.Append (Цифрами (summa * 100 % 100, ПолноеНаименованиеДробнойЧасти, падеж));
sb.Append (')');
sb [i] = char.ToUpper (sb [i]); // сделать первую букву прописи заглавной
return sb.ToString ();
}
static string Прописью (decimal n, string unit, Падеж падеж)
{
return склонятель.Пропись (n, ref unit, падеж) + " " + unit;
}
static string Цифрами (decimal n, string unit, Падеж падеж)
{
склонятель.Пропись (n, ref unit, падеж);
return n.ToString ("00") + " " + unit;
}
static readonly Склонятель склонятель = new Склонятель ();
}
Вот как этот класс можно использовать:
var рубли = new ДенежнаяЕдиница {
ПолноеНаименованиеЦелойЧасти = "рубль",
ПолноеНаименованиеДробнойЧасти = "копейка",
СокращенноеНаименованиеЦелойЧасти = "руб."
};
var евро = new ДенежнаяЕдиница {
ПолноеНаименованиеЦелойЧасти = "евро",
ПолноеНаименованиеДробнойЧасти = "цент",
СокращенноеНаименованиеЦелойЧасти = "евро"
};
Console.WriteLine (рубли.СуммаПрописью (100m));
Console.WriteLine (рубли.СуммаПрописью (300333.12m));
Console.WriteLine (евро.СуммаПрописью (400444.44m));
Console.WriteLine ("За вычетом "
+ рубли.СуммаПрописью (333.12m, Падеж.Родительный));
В результате получим:
100,00 руб. (Сто рублей 00 копеек)
300 333,12 руб. (Триста тысяч триста тридцать три рубля 12 копеек)
400 444,44 евро (Четыреста тысяч четыреста сорок четыре евро 44 цента)
За вычетом 333,12 руб. (Трёхсот тридцати трёх рублей 12 копеек)
Пример 2. Цена договора с НДС
string ПрописьРуб (Падеж падеж, int n)
{
string unit = "рубль";
return n + " (" + склонятель.Пропись (n, ref unit, падеж) + ") " + unit;
}
int цена = 1800;
Console.Write ("Цена договора составляет {0}, ",
ПрописьРуб (Падеж.Винительный, цена));
Console.Write ("в том числе НДС в размере {0}.",
ПрописьРуб (Падеж.Родительный, (int) (цена * 0.18 / 1.18)));
// Цена договора составляет 1800 (одну тысячу восемьсот) рублей,
// в том числе НДС в размере 274 (двухсот семидесяти четырёх) рублей.
Пример 3. Перечень товаров
var товары = new []
{
new {Наименование = "шампур из нержавеющей стали", Количество = 12},
new {Наименование = "решетка-гриль", Количество = 2},
new {Наименование = "щипцы для углей", Количество = 1},
};
foreach (var товар in товары)
{
string unit = товар.Наименование;
Console.WriteLine ("{0,-30} {1,2} ({2})",
товар.Наименование,
товар.Количество,
склонятель.Пропись (товар.Количество, unit));
}
// шампур из нержавеющей стали 12 (двенадцать)
// решетка-гриль 2 (две)
// щипцы для углей 1 (одни)
Пример 4. Социальная сеть
string Новых (int n, string unit)
{
РодЧисло родЧисло = склонятель.Проанализировать (unit).РодЧисло;
unit = склонятель.ИзменитьРод ("новый ", родЧисло) + unit;
склонятель.Пропись (n, ref unit);
return n + " " + unit;
}
Console.WriteLine ("У вас " + Новых (5, "друг")); // «У вас 5 новых друзей»
Console.WriteLine ("У вас " + Новых (1, "сообщение")); // «У вас 1 новое сообщение»
Console.WriteLine ("У вас " + Новых (2, "подарок")); // «У вас 2 новых подарка»
Пример 5. День рождения
string Исполнилось (string кто, int сколько)
{
string unit = "год";
склонятель.Пропись (сколько, ref unit);
return склонятель.Проанализировать (кто).Дательный
+ " " + сколько + " " + unit;
}
Console.WriteLine (Исполнилось ("Анечка", 2)); // «Анечке 2 года»
Console.WriteLine (Исполнилось ("Вовочка", 5)); // «Вовочке 5 лет»
Console.WriteLine (Исполнилось ("Иван Иванович", 51)); // «Ивану Ивановичу 51 год»
Console.WriteLine (Исполнилось ("мы", 10)); // «нам 10 лет»
Попробуйте функцию «Пропись» в действии на сайте summapro.ru.
Защита от несанкционированного использования
Часть сборки Morpher.dll зашифрована и для ее правильной работы необходим лицензионный ключ.
Ключ передается в конструктор класса Склонятель:
var склонятель = new Склонятель ("MRK1.…");
Каждый покупатель получает свой собственный уникальный ключ.
Ключ действует до даты окончания лицензии и подходит ко всем версиям библиотеки, выпущенным до этой даты
(версия 2.15.0 и новее; для более старых версий нужны ключи прежнего формата).
При продлении лицензии вы получаете новый ключ.
Сведения о лицензии доступны через свойство License:
var склонятель = new Склонятель (ключ);
Console.WriteLine (склонятель.License);
DateTime? expiry = склонятель.License.ExpiryDate;
Если ключ неправильный, конструктор выбрасывает LicenseException;
если срок лицензии истёк — LicenseExpiredException
(оба исключения являются ArgumentException).
Исключение LicenseExpiredException может возникнуть и позже, при вызове методов
уже созданного объекта Склонятель, если срок лицензии истёк во время работы программы.
Пользовательский словарь
Пользовательский словарь служит для коррекции склонения отдельных словосочетаний.
Чтобы подключить словарь к библиотеке, нужно передать его в конструктор класса Склонятель:
var склонятель = new Склонятель ("fbvB3vWfnrXQ==", new StreamReader ("MyDict.xml"))
Вызывать StreamReader.Dispose необязательно — за вас это сделает библиотека.
IUserDictionary
Имеется также конструктор, принимающий пользовательский словарь в виде интерфейса
IUserDictionary:
public Склонятель (string key, IUserDictionary userDict);
Интерфейс имеет один метод, который возвращает словарную статью
по заданной форме именительного падежа единственного числа:
public interface IUserDictionary
{
Entry Lookup (string nominativeSingular);
}
Пока этот интерфейс используется только в Локальном веб-сервисе
для кэширования словаря средствами ASP.NET.
История изменений
| Дата |
Версия |
|
| 25.10.2026 |
2.15.0 |
Это самое большое обновление за все время существования модуля.
По порядку:
-
Улучшено склонение:
- Перечисления:
«Сырьё и материалы» → «Сырья и материалов»,
«Спорт и развлечения» → «Спорта и развлечений»,
«Одежда, обувь, аксессуары» → «Одежды, обуви, аксессуаров»
(раньше последнее слово оставалось в именительном падеже).
- Названия товаров: прилагательные в конце теперь склоняются:
- «Йогурт Северная Долина вишнёвый» → «Йогурта Северная Долина вишнёвого»,
- «Мороженое Зимний Вальс сливочное» → «Мороженого Зимний Вальс сливочного»,
- «Молоко Простоквашино пастеризованное» → «Молока Простоквашино пастеризованного».
- Географические названия:
у названий с дефисом теперь склоняется только последняя часть:
- «Ричмонд-парк» → «в Ричмонд-парке»,
- «Блэкпул-Тауэр» → «в Блэкпул-Тауэре»;
раньше: «в Ричмонде-парке», «в Блэкпуле-Тауэре»;
названия с английскими предлогами и слова «Кросс», «Бридж» не склоняются:
«Стратфорд-апон-Эйвон», «Ньюкасл-апон-Тайн», «Кингс-Кросс».
«Марий Эл» не склоняется (раньше «Мария Эл»).
- Выбор предлога. Программа, например, различает:
- Южный Урал → на Южном Урале (регион)
- Новый Урал → в Новом Урале (город)
- Исаакиевское озеро → на Исаакиевском озере (озеро)
- Исаакиевское Озеро → в Исаакиевском Озере (одноименный поселок)
А также:
«на Бейкер-стрит», «на Юнион-сквер», «на Эбби Роуд»,
но «в Красной Поляне» (раньше «на»).
- Составные и иностранные фамилии:
- «Семёнова-Тян-Шанского» (раньше
«Тяна-Шанского»),
- «Хосе Ортеги-и-Гассета» (раньше
«Ортега-и-Гассета»),
- «Сергеем Брином» (раньше
«Бриным»),
- «Леди Гаги» (раньше
«Леди Гага»).
-
Склонение фамилий, совпадающих с названиями городов:
- Одиночная фамилия «Пушкин» теперь склоняется как фамилия, а не как название города:
«Пушкина» в винительном падеже, «Пушкиным» в творительном.
Раньше получались
«Пушкин» (винительный) и «Пушкином».
- То же сделано для фамилий Горький, Жуковский, Мышкин, Жуков, Ломоносов,
Брежнев, Королёв, Серов, Самойлов и Быков.
Киров и Куйбышев по-прежнему склоняются как города.
- Если нужен город или нарицательное слово, передайте
Признак.Нарицательное:
«Пушкин» тогда склоняется как город («Пушкином»).
Если нужна фамилия, передайте Признак.ФИО:
например, чтобы «Кишинёв» склонялся как фамилия («Кишинёвым»).
Всё это касается лишь одиночных слов. В контексте
«город Пушкин», «улица Горького» и «Пушкин Александр» склоняются правильно, как и раньше.
-
Склонение китайских имен.
Фамилия теперь не меняется, а мужское имя склоняется.
- Дэн Сяопин:
Дэна Сяопина → Дэн Сяопина
- Цзян Цзэминь:
Цзяна Цзэминя → Цзян Цзэминя
- Чжоу Эньлай:
Чжоуа Эньлая → Чжоу Эньлая
- Сун Тао:
Суна Тао → Сун Тао
- Сун Цинлин:
Суна Цинлина → Сун Цинлин
- Сунь Ят-сен:
Суня Ят-сен → Сунь Ят-сена
Корректно склоняется сочетание «должность + имя»:
- председатель Си Цзиньпин:
председателя Си Цзиньпин → председателя Си Цзиньпина
«Обрусевшие» склоняются как обычно:
- Виктор Ван:
Виктора Ван → Виктора Вана
- Татьяна Ким → Татьяны Ким
- Склонение вьетнамских и корейских имен.
Они состоят из трёх частей, склоняется только последняя:
«Ким Чен Ира» (раньше
«Кима Чена Ира»), «Фам Ван Донга».
-
Отработан список из 620 географических названий, присланный пользователем
temi4
(uservoice/issues/27):
- Морфер теперь правильно склоняет 613 из 620 названий из списка, например:
«в Тоттори», «в Араукании», «в Касабланка-Сете», «в Мадхья-Прадеше»,
«на Сардинии», «на Восточной Яве».
- Составные иностранные названия:
- Первая часть больше не склоняется там, где не должна:
«в Альта-Верапасе», «в Гранд-Ансе», «в Аш-Шати», «в Бени Аббесе».
- Название с несклоняемой последней частью теперь не склоняется целиком:
«в Моен-Огове», «в Пхёнан-Намдо».
- Хорватские жупании склоняются правильно: «в Загребской жупании».
- Предлог «на» для островов, атоллов и архипелагов:
«на Мадейре», «на Кэт Айленде», «на атолле Джонстон», «на Южной Суматре».
- Названия мест больше не склоняются как одушевлённые:
винительный «Сен-Джон», «Эш-Шамаль», а не
«Сен-Джона», «Эш-Шамаля».
- Местный падеж на «-у» в названиях с «Бор» и «Порт»:
«в Сосновом Бору», «в Мясном Бору», «в Железном Порту»
(спасибо пользователю hisbvdis,
приславшему комментарий).
- Сокращения: «Гл. инженер» → «Гл. инженера»,
«Ст. кладовщик» → «Ст. кладовщика»,
«Ген. директор» →
«Гена. директор» «Ген. директора».
- Составные должности типа «Митрополита Калужского и Боровского».
- «Совет Министров» → «Совета Министров» (раньше
«Министрова»)
- Мягкие переносы (U+00AD) на входе сохраняются на выходе и не мешают склонению
(раньше перенос терялся).
- Исправлено склонение фамилии Романец в соответствии с
комментарием
Yuri Byshko.
-
Найдены и исправлены баги и недочёты:
Пропись(int.MinValue, ref unit, падеж) с любой единицей измерения
приводила к переполнению стека и аварийному завершению процесса.
Пропись(decimal, …) для некоторых чисел от 1015 возвращала пустую строку,
а для 1000000000000001 — просто «один»: старший разряд терялся.
Теперь правильно: «один квадриллион», «один октиллион», «один квадриллион один».
Пропись с отрицательным числом и пустой или неопознанной единицей измерения
(unit = "") возвращала строку «минус »;
для положительных чисел в этом случае возвращался null.
Теперь возвращается null.
- Слова «чертёнок», «бесёнок» склонялись по-разному в зависимости от текущей культуры
(
CurrentCulture).
Объект Склонятель, созданный в инвариантной культуре и использованный
в kk-KZ, давал для «чертенок» множественное число «чертята» (вместо «чертенята»);
созданный в kk-KZ и использованный в инвариантной культуре —
«бесята» для «бесёнок» (вместо «бесенята»).
ИзменитьРод терял «о»/«е» в притяжательных прилагательных на -ов, -ев, -ёв, -ин, -ын:
«отцов» → «отцва», «отцво», «отцвы»;
«мамин» → «мамна».
Теперь «отцова», «отцово», «отцовы», «мамина».
«лисий» → «лисья» работает по-прежнему.
- Пользовательский словарь: форма, которая пуста или состоит из одних знаков препинания
(
<П></П> или <П>...</П>),
вызывала IndexOutOfRangeException при чтении свойства Предложный.
Теперь она возвращается как есть, без добавленного предлога «в».
-
Вместо исключений общего вида теперь выбрасывается
ArgumentException,
ArgumentOutOfRangeException и ArgumentNullException с указанием параметра:
- конструктор класса
Склонятель теперь выбрасывает
ArgumentException при неверном лицензионном ключе
(раньше FormatException, если ключ не является корректной строкой Base64,
и Exception для ключа правильного формата, но неподходящего, например
"AAAAAAAAAAAAAAAAAAAAAA==");
Пропись(…, (Падеж) 99) и ИзменитьРод("синий", (РодЧисло) 99):
теперь выбрасывают
ArgumentOutOfRangeException при значении, которого нет в перечислении
(раньше Exception без указания параметра);
Проанализировать("стол", (Признак[]) null) теперь выбрасывает
ArgumentNullException (раньше NullReferenceException);
- пользовательский словарь с записью без элемента
<singular>
теперь выбрасывает
ArgumentException при создании Склонятель
(раньше NullReferenceException при первом склонении).
- Из публичного API убраны недокументированные типы и методы:
ЯзыкПрописи,
УкраинскийЯзык,
Відминюванник,
IСклоняемоеУкр,
MorpherDictionary.Dict,
а в сборке для .NET 2.0 — вспомогательные классы
System.Linq.Enumerable и ExtensionAttribute.
-
Добавлены тесты:
- потокобезопасность:
параллельные вызовы одного экземпляра
Склонятель дают те же результаты,
что и последовательные
(Склонятель и раньше был потокобезопасным, теперь это проверяется тестом);
- очень длинные фразы: объём работы по разбору одной фразы ограничен.
Если фраза слишком сложная,
Проанализировать возвращает null.
Это оставляет злоумышленникам меньше шансов «подвесить» вызывающий процесс.
Ограничение срабатывает на фразах из порядка 50 слов.
- производительность: для всех публичных методов заданы пределы времени вызова,
что позволит предотвратить возможную регрессию производительности.
- Словарь модуля пополнен более чем на 1000 слов (в основном фамилии и географические названия).
- Размер Nuget-пакета сократился с 2 МБ до 823 КБ за счет вынесения ресурсов в отдельную сборку.
- Изменен формат лицензионного ключа: теперь это строка вида
MRK1.…,
в которой записаны лицензиат, дата начала и дата окончания лицензии.
При обновлении вам понадобится новый ключ.
Ключ подходит ко всем версиям библиотеки, выпущенным до окончания его срока;
чтобы продлить лицензию, достаточно заменить строку ключа, замена библиотеки не нужна.
- Добавлено свойство License с информацией о лицензии:
Licensee (лицензиат), EffectiveDate и ExpiryDate
(даты начала и окончания).
- В случае истечения срока лицензии (или если версия библиотеки выпущена после окончания лицензии)
библиотека честно кидает
LicenseExpiredException
(раньше просто переставала склонять).
|
| 12.04.2026 |
2.14.19 |
-
Учет казахских букв при склонении на русском языке:
в Казахстане типична ситуация, когда ФИО на казахском
вставляется в документ на русском,
и склонение ожидается по правилам русского языка.
Например, Әбіш Кекілбаев должен превратиться в Әбіша Кекілбаева.
Эта версия модуля умеет обрабатывать казахские буквы.
-
Исправлено склонение
фамилии Якушенок,
топонима Айн-Темушент,
фамилии Дыкань.
Исправлено склонение фамилий Семёнова, Фёдорова
(было сломано в версии 2.14.17).
|
| 01.01.2026 |
2.14.18 |
-
Исправлено склонение фамилии Кузьмина́.
Раньше она неправильно склонялась в сочетаниях
Кузьмина Ирина,
Кузьмина К. Э.
-
Пополнение словаря программы из Викисловаря и odict.ru.
|
| 19.07.2025 |
2.14.17 |
-
Добавлены аббревиатуры ГУЗ, ТФОМС и др.
-
Исправлено склонение "Хайсам бен Тарек Аль Саид" и подобных.
-
Исправлено склонение "принт-менеджер".
-
К пакету добавлен тег <Description>.
-
Пополнение словаря odict.ru на 3426 слов.
-
Добавлена инструкция по установке.
|
| 08.08.2024 |
2.14.16 |
-
Значительное пополнение словарей модуля, в основном за счет Викисловаря и
odict.ru.
-
Исправлено склонение:
- фамилии Бова
- фамилии Андрусейко
- аббревиатуры «УМВД»
- названия «Марьина Роща»
- армянского женского имени Аревик
- фраз с несколькими закавыченными словами на примере:
Исполнительный Вице-Президент – управляющий по Южному региону – управляющий Филиалом Банка "Южный" – управляющий Филиалом Банка «Северо-Кавказский»
|
| 20.05.2023 |
2.14.15 |
-
Исправлено склонение:
- фамилии Курячий
- фраз ПРЕДСЕДАТЕЛЬ СОВЕТА ДЕПУТАТОВ, МИНИСТР ФИНАНСОВ ПЕРМСКОГО КРАЯ
- фраз "ул. Ленина", "ул. Пушкина" (с сокращением)
- фразы "Пашкевич С." с указанием женского рода (Признаки.Женский)
- наречий (на основе присланного пользователями примера «технически перевооружаемый»).
- В сочетании «во многом» предлог во, а не в (например, при склонении слова «многое»).
- Несклонение предлогов НА и ДЛЯ (раньше они иногда склонялись - для как тля).
- Сборка Morpher.dll подписана криптографическим ключом.
|
| 08.05.2022 |
2.14.14 |
-
Исправлено склонение слов и фраз, присланных пользователями:
-
Доставка, демонтаж и монтаж
-
Главный конструктор турбомашин
-
Фамилии Черевань, Гудачек
-
Склонение топонима «Красный боец»
-
Несклонение аббревиатуры УФПС
-
СПЕЦИАЛИСТ ТЕХНИЧЕСКОЙ ПОДДЕРЖКИ
-
ИСПОЛНЯЮЩИЙ ОБЯЗАННОСТИ ДИРЕКТОРА
-
УЧАСТОК ПО РЕМОНТУ И ОБСЛУЖИВАНИЮ ЭЛЕКТРООБОРУДОВАНИЯ, КОНТРОЛЬНО-ИЗМЕРИТЕЛЬНЫХ ПРИБОРОВ И АВТОМАТИКИ КИСЛОРОДНОЙ СТАНЦИИ N4, КОМПРЕССОРНЫХ СТАНЦИЙ N
-
Исправлено склонение имен типа Аслан-бек, Джалил-бек.
-
В словарь добавлены названия растений: газания, дугласия, сансевиерия и др.
-
Слова перевал, застава, месторождение и др.
теперь получают предлог «на» в местном падеже.
-
Предлог «на» для сокращения «ул»: «на ул. Фрунзе», «на Тенистой ул.»
Всего в модуль добавлено 70152 новых слова из Викисловаря,
odict.ru
и 6-го издания словаря Зализняка.
|
| 15.04.2022 |
2.14.13 |
Версия получилась непригодной к использованию и была заменена на 2.14.14.
|
| 09.04.2021 |
2.14.12 |
-
Добавлено 25 тысяч слов из русского Викисловаря.
-
Добавлено более 14600 новых слов
(новое издание словаря Зализняка
+ пополнение словаря odict.ru).
-
Добавлено 752 фамилии из Википедии.
-
Функция Пропись теперь считает единицы измерения нарицательными.
-
Улучшено склонение несловарных ФИО, а также фамилий с дефисом (Тер-Оганесян, Кул-Мухаммед)
-
Функция склонения больше не заменяет латинские буквы на русские.
-
Исправлено склонение Шугыла Нурсабикызы и подобных
(где -кызы пишется слитно).
-
Исправлено склонение нестандартной фамилии Василив.
-
Исправлено склонение нестандартного топонима Уторгош,
который склоняется и по мужскому, и по женскому типу:
Малая Уторгош и Малый Уторгош.
-
Орёл теперь склоняется как неодушевленное (название города).
-
Исправлено склонение Илон Маск, контакт-центр.
-
Исправлено склонение смартфон samsung galaxy j3 sm-j330f ds черный.
-
Исправлено склонение Смартфон Apple iPhone 11 Pro Max 256GB Midnight Green (MWHM2RU/A).
-
В украинский словарь добавлены имена Регіна, Альвіна, Фаїна, Рамін
и фамилия Краснящих.
|
| 12.06.2020 |
2.14.11 |
- Исправлено склонение ряда женских имен Ближнего Востока:
Алмаз, Анушик, Алтнат и др.
- Исправлено склонение отдельных словосочетаний: Кива Владимир, Кабинет Министров, мешок.
- Добавлено 90 новых слов.
-
Функция склонения прилагательных
теперь учитывает притяжательные прилагательные
(лисий, третий).
- Теперь не склоняются слова в кавычках: Сторожевой корабль «Сметливый».
|
| 27.12.2019 |
2.14.10 |
Добавлено 250 новых слов.
Функция идентификации фамилии, имени и отчества теперь учитывает инициалы.
|
| 10.09.2018 |
2.14.9 |
Возобновлена поддержка .NET Framework 2.0. Добавлено 63 новых слова.
|
| 14.06.2018 |
2.14.8 |
Добавлено 65 новых слов, в том числе "прайс-каталог".
|
| 13.05.2018 |
2.14.7 |
Исправлена ошибка в методе ИзменитьРод:
для прилагательного большой в среднем роде он теперь возвращает большое вместо неправильного большее.
Корректно обрабатываются наречия: отдельно ("отдельно стоящее здание"), слегка, почти, совершенно.
|
| 12.04.2018 |
2.14.6 |
Исправлена ошибка в методе Пропись:
неправильное склонение слова человек в дательном, творительном и предложном падежах.
235 новых слов (в основном географические названия).
Исправлена проблема со строгим именем сборки, имевшаяся в версии 2.4.14: сборка была в состоянии delay-signed и поэтому при попытке загрузки из сборки со строгим именем выдавалась ошибка "Сбой при проверке правильности строгого имени" (Strong name validation failed).
Начиная с этого релиза номер версии сборки (AssemblyVersion) заморожен на значении 2.14.4.31693 и не будет меняться, пока не изменится API библиотеки. Это сделано для того, чтобы Morpher.dll можно было подменить на более новую версию без перекомпиляции остального приложения.
|
| 20.01.2018 |
2.14.4 |
Исправлено склонение узбекской денежной единицы тийин.
В этой версии была проблема со строгим именем сборки, исправленная в версии 2.14.6.
|
| 04.09.2017 |
2.14.3 |
Исправлена разбивка ФИО на составляющие для фамилии Вакула.
|
| 04.09.2017 |
2.14.2 |
Исправлено склонение "Член Правления, директор по операциям".
|
| 29.08.2017 |
2.14.1 |
Исправлено возвращение разбиение ФИО при добавлении ФИО в пользовательский словарь.
|
| 31.07.2017 |
2.14.0 |
Поддержка .NET Standard 2.0.
|
| 12.02.2017 |
2.13.5 |
Ограничено слишком агрессивное исправление латиницы на кириллицу, пополнение словаря.
|
| 05.02.2017 |
2.13.4 |
Исправлена ошибка в методе Пропись. Ошибка проявлялась только для слова год
в винительном падеже при n=1.
|
| 28.01.2017 |
2.13.3 |
Пополнение словаря. В частности, добавлены слова и сокращения:
фальш-камера, кабель-канал, ИБП, УЗО и др.
|
| 04.06.2016 |
2.13.1 |
Пополнение словаря. В частности, исправлено склонение словосочетания
ТК-10 СИДиСР МВД.
|
| 23.08.2015 |
2.12.0 |
В предыдущих версиях было невозможно вызвать метод Пропись из Visual Basic.
Теперь это ограничение устранено путем удаления перегрузок метода,
где параметр unit фигурировал без модификатора ref.
|
| 17.01.2015 |
2.11.0 |
Добавлена функция ИзменитьРод.
|
| 7.12.2014 |
2.10.3 |
Пополнение словаря (601 новое слово, в основном географические названия).
|
| 11.11.2014 |
2.10.2 |
-
Улучшено склонение и определение рода имен, записанных полностью заглавными буквами.
Например, раньше неправильно определялся род в имени ЧЕРНЫШЕВА ЮЛИЯ ВЛАДИМИРОВА.
Теперь определяется как женский, несмотря на опечатку в отчестве.
-
Устранено исключение, возникавшее для "слов" на "-й" или "-ь", например Нью-Й или ночь-ь.
|
| 29.10.2014 |
2.10.1 |
Пополнение словаря (109 новых слов). В частности, исправлено склонение распространенного в Казахстане имени Бахыт,
которое бывает и у мужчин, и у женщин, например:
| Мужчины | Женщины |
| Бахыт Килибаев | Бахыт Жуматова |
| Бахыт Арыстанов | Бахыт Сыдзыкова |
| Бахыт Кенжеев | Бахыт Бегенова |
|
| 17.09.2014 |
2.10.0 |
Добавлена функция разбивки ФИО на составляющие.
|
| 17.09.2014 |
2.9.2 |
- Исправлено склонение наименования Наконечник E-Cu M 6/0,6/D=6,0/25,0 и подобных.
- Названия со словом "набережная" теперь имеют предлог "на" в местном падеже: на Крутицкой набережной.
- Пополнение словаря (106 новых слов)
|
| 27.08.2014 |
2.9.0 |
Добавлена возможность указания одушевленности входного слова или словосочетания
при помощи значений
Признак.Одушевлённое и
Признак.Неодушевлённое.
Такая возможность нужна для различения слов, которые могут называть лиц или предметы:
укупорщик, взбиватель, тестер.
|
| 17.08.2014 |
2.8.1 |
Пополнение словаря программы за счет Словаря новых слов (более 7200 статей).
|
| 17.08.2014 |
2.8.0 |
Исправлена ошибка в прописи чисел вида ... x1y abc, где x=1..9, y=1..4, abc - любые 3 цифры, а ... - любая последовательность цифр, в т.ч. нулевой длины.
Пример числа: 311 000. Ошибка проявлялась только в родительном падеже (трёхсот одиннадцати ТЫСЯЧИ вместо трёхсот одиннадцати ТЫСЯЧ).
|
| 5.07.2014 |
2.7.4 |
Для помидоров, баклажанов и подобных названий (с пометой ["двойка в кружке"] по Зализняку) в родительном множественного теперь выдается форма с окончанием -ов, а не нулевым.
|
| 18.02.2014 |
2.7.3 |
Улучшено распознавание ФИО для составных имен. Теперь входное словосочетание признается ФИО, если
хотя бы один из разделенных дефисом компонентов известен как имя. В результате стали правильно склоняться
такие имена как ГЕЙ-ЛЮССАК Жозеф-Луи, Кени Шарль-Андре, Гильермо Гомес-Пенья и другие.
|
| 20.11.2013 |
2.7.0 |
- Поддержка числительных с наращением (1-я Парковая улица, 5-е колесо).
- Из входной строки теперь удаляются мягкие переносы (U+00AD).
- Добавлен встроенный словарь исключений.
- Небольшое пополнение основного словаря (около 30 слов).
|
| 23.09.2013 |
2.6.2 |
Исправлена ошибка в прописи числа 0,2 в винительном падеже. Эта ошибка касалась только чисел 0,2, 0,002, 0,000002 и т.д. и проявлялась только в винительном падеже ("двух десятых" вместо "две десятых").
|
| 4.08.2013 |
2.6.1 |
В словарь добавлено более 400 популярных английских имен: Крис, Джеймс, Гарри, Уэйн... Элизабет, Уитни...
Это поможет программе более правильно склонять английские имена и определять их пол.
|
| 2.08.2013 |
2.6.0 |
Функция Пропись теперь работает с дробными числами: 5,3% (пять целых три десятых процента).
Кроме того, расширен диапазон допустимых чисел и теперь он покрывает все возможные значения типа decimal.
В связи с этим упразднено свойство MaxDecimal.
|
| 30.06.2013 |
2.5.2 |
Исправлена ошибка в функции Пропись: для единиц измерения во множественном числе (сутки) в косвенных падежах функция возвращала null.
Теперь склоняется корректно: в течение трёх суток. Добавлены юнит-тесты, чтобы не допустить повторения этой проблемы в будущем.
Количество юнит-тестов для функции Пропись перевалило за 200.
|
| 23.06.2013 |
2.5.1 |
Пополнение словаря: проверено склонение более 200 стран и исправлены все ошибки.
Особую трудность составило сокращение о-в (остров). Теперь это сокращение склоняется корректно:
о-в Святой Елены,
о-ва Туркс и Кайкос.
|
| 18.06.2013 |
2.5.0 |
Добавлен интерфейс IUserDictionary для работы с пользовательским словарем. |
| 24.03.2013 |
2.4.0 |
Добавлена возможность корректировки склонения при помощи пользовательского словаря. |
| 07.02.2013 |
2.3.9 |
В словарь добавлены названия минералов: анортоминасрагрит, балгарит, блёдит, вантгоффит... |
| 30.01.2013 |
2.3.8 |
Исправлено склонение словосочетаний "Краснодарский край и Республика Адыгея" и "Республика Саха (Якутия)". |
| 12.01.2013 |
2.3.7 |
Исправлена ошибка в склонении отчества Николаевна и подобных. |
| 23.12.2012 |
2.3.6 |
Реализована защита от несанкционированного использования. |
| 4.12.2012 |
2.3.5 |
К сборке добавлен атрибут AllowPartiallyTrustedCallers для решения проблемы с использованием сборки в Reporting Services. |
| 30.09.2012 |
2.3.4 |
Учет аббревиатуры "и.о." (исполняющий обязанности), небольшое пополнение словаря. |
| 15.06.2012 |
2.3.3 |
В функцию Пропись добавлен учет единиц измерения, не имеющих единственного числа: двое суток, одни ножницы и т.п. |