Count russian nouns with correct declination/pluralization (Счет существительных в русском языке)

<?php
 
function ru_noun_genetive($word, $gender, $plural) {
	/* Apply "go archaic" mutation! */
	if ($gender == 'f') {
			$word = preg_replace ( "/([^ср])ть$/u", "$1терь" , $word );
			$word = preg_replace ( "/чь$/u", "$1черь" , $word );
	}
 
	/* Masculine words that look feminine (SUPER HACK!) */
	if ($gender == 'm' && preg_match( "/(а|я)$/u", $word)) $gender = 'f'; 
 
	/* Apply endings ('The Rules') */
	if (!$plural) { //genetive case / singular
		if ($gender == 'm') {
			$word = preg_replace ( "/([^аеийоуьыэюя])$/u", "$1а" , $word );
			$word = preg_replace ( "/й$/u", "я" , $word );
			$word = preg_replace ( "/ь$/u", "я" , $word );
		}
		if ($gender == 'f') {
			$word = preg_replace ( "/а$/u", "ы" , $word );			
			$word = preg_replace ( "/ь|я$/u", "и" , $word );
		}
		if ($gender == 'n') {
			$word = preg_replace ( "/о$/u", "а" , $word );
			$word = preg_replace ( "/е$/u", "я" , $word );
		}
	}
	if ($plural) { //genetive case / plural
		if ($gender == 'm') {
			$old_word = $word;
			$word = preg_replace ( "/й$/u", "ев" , $word);
			$word = preg_replace ( "/([жчшщ])$/u", "$1ей" , $word);			
			$word = preg_replace ( "/(ц)$/u", "$1ев", $word);
			$word = preg_replace ( "/ь$/u", "ей" , $word);
			if ($word == $old_word) 
				$word = preg_replace ( "/([^аеиоуэюя])$/u", "$1ов" , $word);
		}
		if ($gender == 'f') {
			$word = preg_replace ( "/([^аеиоуэюя])я$/u", "$1ь" , $word );
			$word = preg_replace ( "/([аеиоуэюя])я$/u", "$1й" , $word );
			$word = preg_replace ( "/а$/u", "" , $word );
			$word = preg_replace ( "/ь$/u", "$1ей" , $word );
		}
		if ($gender == 'n') {
			$word = preg_replace ( "/о$/u", "" , $word );
			$word = preg_replace ( "/ие$/u", "ий" , $word );
			$word = preg_replace ( "/е$/u", "ей" , $word );
		}
	}
 
	/* Apply "consonant expansion" mutation */
	if ($gender == 'n') {
			$word = preg_replace ( "/кн$/u", "кон" , $word );
	}
	if ($gender == 'n') {
		if (!$plural) {
			$word = preg_replace ( "/мя$/u", "мени" , $word );
		}
		if ($plural) {
			$word = preg_replace ( "/мя$/u", "мён" , $word );
			$word = preg_replace ( "/сл$/u", "сел" , $word );
		}
		/* Apply 'flavor' */
			$word = preg_replace ( "/ця$/u", "ца" , $word );//singular
			$word = preg_replace ( "/([цщ])ей$/u", "$1" , $word );//plural
			$word = preg_replace ( "/([с])емён$/u", "$1емян" , $word );//plural	
	}
	/* Apply "Double consonant" mutation */
	if ($gender == 'f' || $gender == 'n') {
		if ($plural) {
			$word = preg_replace ( "/е([чршт])к$/u", $1ок" , $word ); //femin
			$word = preg_replace ( "/([чршт])к$/u", "$1ек" , $word ); //neuter
			$word = preg_replace ( "/([лмн])к$/u", "$1ок" , $word );
			$word = preg_replace ( "/([к])л$/u", "$1ол" , $word );
		}
	}
	/* Apply Palatalization */
	if ($gender == 'm' || $gender == 'f') {
			$word = preg_replace ( "/([дт])([ея])([дт])ей$/u", "$1$2$3ь" , $word );//1
	}
	if ($gender == 'm') {
			$word = preg_replace ( "/еней$/u", "ней" , $word );//1
			$word = preg_replace ( "/еня$/u", "ня" , $word );//0
 
			$word = preg_replace ( "/ецев$/u", "цов" , $word );//1
			$word = preg_replace ( "/еца$/u", "ца" , $word );//0
 
			$word = preg_replace ( "/оков$/u", "ков" , $word );//1
			$word = preg_replace ( "/ока$/u", "ка" , $word );//0
 
			//моха-мха мохов-мхов
			$word = preg_replace ( "/охов$/u", "хов" , $word );//1
			$word = preg_replace ( "/оха$/u", "ха" , $word );//0
 
 
			$word = preg_replace ( "/(р)отов$/u", "$1тов" , $word );//1
			$word = preg_replace ( "/(р)ота$/u", "$1та" , $word );//0
 
		if ($plural) {
			/* Handle "chibi suffix" */
			$word = preg_replace ( "/ёнков$/u", "ят" , $word );
			/* Make softer sound */
			$word = preg_replace ( "/(коло)сов$/u", "$1сьев" , $word );
			$word = preg_replace ( "/([^аеиоуэюя])(р[а])тов$/u", "$1$2тьев" , $word );
			$word = preg_replace ( "/зей$/u", "зьев" , $word );
			$word = preg_replace ( "/([е])ртов$/u", "$1ртей" , $word );
			$word = preg_replace ( "/ынов$/u", "ыновей" , $word );//1			
		}
		$word = preg_replace ( "/лия$/u", "лья" , $word );//0 -2улия -2улья
		$word = preg_replace ( "/ея$/u", "ья" , $word );//0 -2соловея -2соловья
		$word = preg_replace ( "/еев$/u", "ьев" , $word );//1 -5соловеев -5соловьев
	}
	/* remove consonat from root */
	//$
	//День, лев, лёд, лён, лоб, мох, пень, пёс, ров, рот, сон, шов
	//Рожь, ложь, вошь.
	if ($gender == 'n') {
			$word = preg_replace ( "/ев$/u", "евьев" , $word );//1 деревев -- деревьев
			$word = preg_replace ( "/(.)рыл$/u", "$1рыльев" , $word );//1крыл -- крыльев			
	}
	if ($gender == 'f') {
			$word = preg_replace ( "/пк$/u", "пок" , $word );//0
 
			$word = preg_replace ( "/([пм])лей$/u", "$1ель" , $word );//1
	}
 
	/* Apply Russian Spelling Rules */
	$word = preg_replace ( "/([гкхжчшщ])ы$/u", "$1и" , $word );
	$word = preg_replace ( "/([гкхжчшщ])я$/u", "$1а" , $word );
	$word = preg_replace ( "/([гкхжчшщ])ю$/u", "$1у" , $word );	
 
	/* Done! :) */
	return $word;// . "[$plural, $gender]";
}
 
function ru_noun_count($quantity, $word, $spell_number = 1) {
 
	static $s_list = array( 
		/* Never plural */
		"буржуа", "кофе"
	);
 
	$gender = ru_noun_gender($word);
 
	$mode = ru_number_case($quantity);
 
	if ($spell_number) $quantity = ru_number($quantity, $gender);
 
	if (in_array($word, $s_list)) $mode = 0;
 
	if ($mode) $word = ru_noun_genetive($word, $gender, $mode-1);
 
	return $quantity . " " . $word;
}
 
/* Unit test
 * Prepare 'testlist.txt' in format:
 * ночь ночи ночей\n */ 
$lines = split("\n", file_get_contents('code/testlist.txt'));
foreach ($lines as $line) {
	list($word, $gs, $gp) = split(" ", $line);
 
	$gender = ru_noun_gender($word);
 
	$mgs = ru_noun_genetive($word, $gender, 0);
	$mgp = ru_noun_genetive($word, $gender, 1);
 
	if ($mgs != $gs || $mgp != $gp) {
		echo "$word [$gender] -- [0] $mgs (need - $gs) -- [1] $mgp (need - $gp)<BR>"; 
	}
} 
 
 
/* Sample */
 $words = array("cайт","заказ","товар","пользователь","файл",
 "модератор","приложение","билет","дело","коммент","комментарий",
 "страница","пост","запись","мегабайт","голос","нетопырь","цапля","зуй","филин","сова",
 "птенец", "сон", "стон", "клин", "блин");
 foreach ($words as $word) {
 	$number = rand(0, 20);
 	echo ru_noun_count($number, $word) . "<BR>"; 
 } 
 echo "Неверно: " .ru_noun_count(22, "хлеб", 0) . "      <BR>";
 echo "Следует: " .ru_noun_count(22, "кусок", 0) . " хлеба<BR>";
 
php?>
буржуа [m] -- [0] буржуы (need - буржуа) -- [1] буржу (need - буржуа)
кофе [n] -- [0] кофя (need - кофе) -- [1] кофей (need - кофе)
октябренок [m] -- [0] октябренка (need - октябренка) -- [1] октябренков (need - октябрят)
котенок [m] -- [0] котенка (need - котенка) -- [1] котенков (need - котят)
щенок [m] -- [0] щенка (need - щенка) -- [1] щенков (need - щенят)
вошь [f] -- [0] воши (need - вши) -- [1] вошей (need - вшей)
ухо [n] -- [0] уха (need - уха) -- [1] ух (need - ушей)
глаз [m] -- [0] глаза (need - глаза) -- [1] глазов (need - глаз)
волос [m] -- [0] волоса (need - волоса) -- [1] волосов (need - волос)
лев [m] -- [0] лева (need - льва) -- [1] левов (need - львов)
лёд [m] -- [0] лёда (need - льда) -- [1] лёдов (need - льдов)
лён [m] -- [0] лёна (need - льна) -- [1] лёнов (need - льнов)
лоб [m] -- [0] лоба (need - лба) -- [1] лобов (need - лбов)
пёс [m] -- [0] пёса (need - пса) -- [1] пёсов (need - псов)
ров [m] -- [0] рова (need - рва) -- [1] ровов (need - рвов)
сон [m] -- [0] сона (need - сна) -- [1] сонов (need - снов)
шов [m] -- [0] шова (need - шва) -- [1] шовов (need - швов)
рожь [f] -- [0] рожи (need - ржи) -- [1] рожей (need - ржей)
ложь [f] -- [0] ложи (need - лжи) -- [1] ложей (need - лжей)
вошь [f] -- [0] воши (need - вши) -- [1] вошей (need - вшей)
шесть cайтов
четырнадцать заказов
четыре товара
двадцать пользователей
ноль файлов
шестнадцать модераторов
двенадцать приложений
четырнадцать билетов
восемнадцать дел
двадцать комментов
три комментария
одинадцать страниц
ноль постов
двенадцать записей
тринадцать мегабайтов
двадцать голосов
десять нетопырей
девятнадцать цапель
два зуя
двенадцать филинов
шестнадцать сов
девять птенцов
двадцать сонов
четыре стона
одинадцать клинов
четыре блина
Неверно: 22 хлеба
Следует: 22 куска хлеба