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