There is a word in the nominative case, the singular. It is necessary to translate it into another case and / or number. For PHP.

For example:

  • red -> (many numbers) red
  • Oleg -> (born pad.) Oleg
  • Feodosiya -> (pred. Pad.) Feodosia
  • (more complicated, since only in the plural.) Kizhi -> (pred. case) Kizhi

Found phpMorphy . In general, it works. But he does not cope with Theodosius (believes that this is a man named Theodosius). The project does not develop, it is not clear how to update the dictionaries.

What else can you use for this task?

1 answer 1

I did not find solutions on php.

But I found the following alternatives:

As a result, I wrote a console script in JS, which translates the word into the desired form. I call the script from PHP through exec() , it works for a long time, so I’m caching the results.

To achieve a good result, the script also has to specify the original form of the word, otherwise it is possible that instead of the noun “stump” the verb “foam” will be returned.

Here is an example of the script:

 $ node ./az.js красный nomn plur Олег nomn gent Феодосия nomn loct Кижи nomn loct красные олега феодосии кижах 

Here is the script itself (sorry, I'm writing as much as I can to JS):

 "use strict"; var tasks = []; // Принимаем аргументы в формате: // // СЛОВО ИСХОДНАЯ_ФОРМА ТРЕБУЕМАЯ_ФОРМА [ СЛОВО ИСХОДНАЯ_ФОРМА ТРЕБУЕМАЯ_ФОРМА ... ] // // Для каждого запрошенного слова выводит результат в виде нужной формы или пустой строки, // если преобразовать не получилось. // Исходная/требуемая форма задается в виде набора граммем через запятую. // Граммемы: http://opencorpora.org/dict.php?act=gram // // Пример: // node ./az.js пень NOUN,nomn datv,plur Феодосия Geox loct // // Переводит слово "пень", которое является существительным (NOUN) (а не глаголом "пенить") // в именительном падеже (nomn) в дательный падеж (datv) мн. число (plur) --> "пням". // А также переводит "Феодосия" (город Geox, а не мужское имя Феодосий) к предложному // падежу --> "Феодосии" // // Выводит результат на 2 строчках: // // пням // феодосии // // Разбираем аргументы process.argv.forEach(function (val, index, array) { // первые два аргумента - node и script if (index < 2) return; // номер блока из 3 аргументов (слово, исходная, требуемая) (zero-based) var block = Math.floor((index + 1) / 3 - 1); // номер аргумента в блоке (zero-based) var arg = (index + 1) % 3; if (typeof tasks[block] === "undefined") { tasks[block] = { word: null, form: null, inForm: null }; } if (arg == 0) { // слово tasks[block].word = val; } else if (arg == 1) { // исходная форма tasks[block].inForm = val.split(","); } else { // требуемая форма tasks[block].form = val.split(","); } }); var Az = require('az'); Az.Morph.init(function() { // выводим результат построчно solveTasks(tasks).every(elem => console.log(elem) || true); function solveTasks(tasks) { var result = []; tasks.forEach(function (val, index, array) { // морфологический разбор var parses = Az.Morph(val.word, { stutter: false}); // ищем в вариантах слово в нужной форме var word = null; for (var i in parses) { // console.log(parses[i].word); // console.log(parses[i].tag); // Если tag содержит все граммемы, которые присутствовали в inForm, // значит это наше слово. if (arrayContainsArray(Object.keys(parses[i].tag), val.inForm)) { // нашли word = parses[i]; break; } } if (!word) { // не нашли result.push(""); // result.push(val.word); } else { // нашли result.push(word.inflect(val.form).word); } }); return result; } function arrayContainsArray(bigger, smaller) { // возвращает true, если все элементы массива smaller присутствуют в bigger // https://stackoverflow.com/questions/15514907/determining-whether-one-array-contains-the-contents-of-another-array-in-javascri return smaller.every(elem => bigger.indexOf(elem) > -1); } });