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 куска хлеба