adminvps

Простейшая функция склонения слов после числительных

На WordPress-сайтах, как правило, информация о количестве комментариев выглядит текстом вида комментариев: 21. Более красиво это выглядело бы так: 21 комментарий.

WordPress, естественно, не учитывает особенности русского языка, когда окончание слова после числа меняется в зависимости от этого числа.

Я предлагаю вашему вниманию простейшую PHP-функцию, которая решает данную задачу. Покажу 2 варианта этой функции.

Вариант 1

Когда нужен текст вида 21 комментарий.

В файле functions.php темы вставляем функцию:

function plural_form($number, $after) {
	$cases = array (2, 0, 1, 1, 1, 2);
	echo $number.' '.$after[ ($number%100>4 && $number%100<20)? 2: $cases[min($number%10, 5)] ];
}

А в то место, где нужно выводить текст о количестве комментов, вставляем такой код:

<?php
plural_form(
	get_comments_number(),
	/* варианты написания для количества 1, 2 и 5 */
	array('комментарий','комментария','комментариев')
);
?>

Вариант 2

Когда нужен текст вида опубликован 21 комментарий. Т.е. в данном случае склоняется слово и перед числом, и после числа.

В файле functions.php темы вставляем функцию:

function plural_form($number,$before,$after) {
	$cases = array(2,0,1,1,1,2);
	echo $before[($number%100>4 && $number%100<20)? 2: $cases[min($number%10, 5)]].' '.$number.' '.$after[($number%100>4 && $number%100<20)? 2: $cases[min($number%10, 5)]];
}

А в то место, где нужно выводить текст о количестве комментов, вставляем такой код:

<?php
plural_form(
	get_comments_number(),
	/* варианты написания для количества 1, 2 и 5 */
	array('опубликован','опубликовано','опубликовано'),
	array('комментарий','комментария','комментариев')
);
?>

Если нужно, чтобы текст был ссылкой, тогда делаем так:

<a href="<?php the_permalink() ?>#comments">[тут вставляем вышеуказанный PHP-код, который выводит количество комментов]</a>

Вот, собственно, и все.

Комментарии (18)
  1. 1
    Евгений
    @

    Спасибо за функцию.
    Но возник вопрос, как быть если при отсутствии комментариев выводилось не «0 комментариев», а «Нет комментариев»?

  2. 4
    Павел
    @

    Здравствуйте! Подскажите пожалуйста, как склонить выражение:
    — если одна рубрика, то «Опубликовано в рубрике»;
    — если рубрик несколько, то «Опубликовано в рубриках».

    Буду признателен за помощь.

  3. 7
    Александр

    Что то вы тут велосипеды придумываете.
    Начну с этого:

    switch($number) {
     case 1:
     echo "Опубликовано в рубрике";
     break; 
     default:
     echo "Опубликовано в рубриках";
    }
    

    Тут достаточно простого условия:

    echo ($number ? 'Опубликовано в рубриках' :'Опубликовано в рубрике');

    Незачем строить конструкции из свитчей без надобности.
    Теперь перейдем к самой функции склонения.
    Вот тут: (Извиняюсь конечно)

    function plural_form($number,$before,$after) {
     $cases = array(2,0,1,1,1,2);
     echo $before[($number%100>4 &amp;&amp; $number%100<20)? 2: $cases[min($number%10, 5)]].' '.$number.' '.$after[($number%100>4 &amp;&amp; $number%100<20)? 2: $cases[min($number%10, 5)]];
    }

    Но это бред сивой кобылы.
    Достаточно просто переписать нормально функцию например вот так:
    Это функция моя просто название поставил ваше.

    function plural_form($n, $w, $t = false){
     $c = array(2, 0, 1, 1, 1, 2);
     return (!$t ? $n.' ' : '').$t[ ($n % 100 > 4 &amp;&amp; $n % 100 < 20) ? 2 : $c[min($n % 10, 5)] ];
    }
    

    А теперь вывод:

    echo plural_form($count,array('опубликован','опубликовано','опубликовано'),1).' '.plural_form($count, array('комментарий','комментария','комментариев'));
    

    Тем самым немного изменив функцию мы убиваем сразу несколько зайцев.
    1. Нам больше не надо изменять функцию. Так как она подойдет для всего.
    2. Мы расширили функционал сайта. И немного уменьшили нагрузку.(Хотя для Wp давно забило о наблюдении за нагрузкой)

    • 8
      Евгений

      Добрый день. А как все это можно преобразовать в вордпресовский шорткод?

      У меня есть шорткод, который выводит количество записей в категории:

      /* Шорткод кол-ва записей */
      function kol_zap($atts) {
      extract(shortcode_atts(array(
      "id" => ''
      ), $atts));
      $post_count = get_category($id)->category_count;
      $cat_name = get_category($id)->name;
      $cat_slug = get_category($id)->slug;
      return ''.$post_count.'';
      }
      add_shortcode('kolvo', 'kol_zap');
      

      Хотелось, чтобы этот шорткод выводил после числа — слово запись(‘и’, ‘ей’).

      Заранее спасибо.

  4. 9
    Виталий Анохин

    Доработал вашу функцию =)
    Теперь есть все проверки, проще задать текст в переменной и можно его отключать.

    <?php
    
    function plural_form($number,$before,$after,$ifzero) {
     if ($number == 0) {echo $ifzero;} else {
     $cases = array(2,0,1,1,1,2);
     if ($before <> 0) {echo $before[($number%100>4 &amp;&amp; $number%100<20)? 2: $cases[min($number%10, 5)]].' ';}
     echo $number;
     if ($after <> 0) {echo ' '.$after[($number%100>4 &amp;&amp; $number%100<20)? 2: $cases[min($number%10, 5)]];}
     }
    }
    
    $anynumber = 55; // число которое надо описать
    $anytextformbefore = array('продан','продано','продано');
    //если указать значение 0 вместо массива, то текст не выводится
    $anytextformafter = array('билет','билета','билетов');
    $anytextformifzero = "билетов нет";
    
    plural_form($anynumber, $anytextformbefore, $anytextformafter, $anytextformifzero);
    
    ?>
    
  5. 10
    Виталий Анохин

    А если надо записать текст в переменную, что будет правильно, то код будет такой

    <?php
    	function plural_form($number,$before,$after,$ifzero) {
    		if ($number == 0) {return $ifzero;} else {
    			$retval = "";
    			$cases = array(2,0,1,1,1,2);
    			if ($before <> 0) {$retval .= $before[($number%100>4 &amp;&amp; $number%100<20)? 2: $cases[min($number%10, 5)]].' ';}
    			$retval .= $number;
    			if ($after <> 0) {$retval .= ' '.$after[($number%100>4 &amp;&amp; $number%100<20)? 2: $cases[min($number%10, 5)]];}
    			return $retval;
    		}
    	}
    
    	$anynumber = 55; // число которое надо описать
    	$anytextformbefore = array('продан','продано','продано');
    	//если указать значение 0 вместо массива, то текст не выводится
    	$anytextformafter = array('билет','билета','билетов');
    	$anytextformifzero = "билетов нет";
    	// результат в переменной
    	$strtext = plural_form($anynumber, $anytextformbefore, $anytextformafter, $anytextformifzero);
    	echo $strtext;
    ?>
    
  6. 11
    Иван

    Здавствуйте! Использовал вашу функцию, был доволен, но столкнулся с такой проблемой. При поиске нашлось 15 материалов и выдало такую ошибку:
    По Вашему запросу
    Notice (8): Undefined offset: 2 [APP\View\Helper\SearchingHelper.php, line 10] 15 ответов :

    вызываю так

    echo plural_form(count($search_res), ['найден', 'найдено'], ['ответ', 'ответа', 'ответов'])
    

    а код функции как в этой статье — Вариант 2
    Подскажите как решить эту проблемку.

  7. 12
    Антон
    @

    Здравствуйте, а как использовать для склонения поисковых запросов? Пример: Найдено (найден) NN поисковых запроса, запросов или запрос.
    Код из двух вариантов отображения ниже:

    <?php echo $count ?> <?php echo _n('поисковый запрос', 'поисковых запроса', $count, 'blockster-wp') ?>
  8. 14
    Антон
    @

    Благодарю, так намного лучше, вот только как учесть нормы склонения двух языков, когда для сайта используется английский и русский? Ведь текст перевода внесен в файл .PO. Или никак.

  9. 16
    Олег
    @

    Спасибо за функцию. Оказалась очень полезна.
    Но я ее немного доработал.
    Может кому пригодится.

    Сами функции:

    <?php
    	function get_decline($value,$string) {
    		$cases = array(2,0,1,1,1,2);
    		return $string[($value%100>4 &amp;&amp; $value%100<20)? 2: $cases[min($value%10, 5)]];
    	}
    	
    	function get_decline_string($prefix,$value,$suffix, $in_array = false) {
    		$cases = array(2,0,1,1,1,2);
    		$prefix_value = $prefix;
    		if(is_array($prefix)){
    			$prefix_value = get_decline($value,$prefix);
    		}
    		$suffix_value = $suffix;
    		if(is_array($suffix)){
    			$suffix_value = get_decline($value,$suffix);
    		}
    		if($in_array == true){
    			return array(
    				'prefix' => $prefix_value,
    				'value' => $value,
    				'suffix' => $suffix_value
    			);
    		} else {
    			return $prefix_value.$value.$suffix_value;
    		}
    	}
    ?>
    

    Варианты использования

    <?php
    	/* количество комментариев */
    	$comments = 5;
    	
    	/* вариант 1 */
    	$var1 = get_decline_string(
    		/* варианты написания префикса для количества 1, 2 и 5 */
    		array('опубликован ','опубликовано ','опубликовано '),
    		/* число */
    		$comments,
    		/* варианты написания суффикса для количества 1, 2 и 5 */
    		array(' комментарий',' комментария',' комментариев')
    	);
    	
    	/* вариант 2 */
    	$var2 = get_decline_string(
    		/* префикс */
    		'опубликовано: ',
    		/* число */
    		$comments,
    		/* варианты написания суффикса для количества 1, 2 и 5 */
    		array(' комментарий',' комментария',' комментариев')
    	);
    	
    	/* вариант 3 */
    	$var3 = get_decline_string(
    		/* варианты написания префикса для количества 1, 2 и 5 */
    		array('опубликован: ','опубликовано: ','опубликовано: '),
    		/* число */
    		$comments,
    		/* суффикс */
    		' комм.'
    	);
    	
    	/* вариант 4 */
    	$var4 = get_decline_string(
    		/* префикс */
    		null,
    		/* число */
    		$comments,
    		/* суффикс */
    		array(' комментарий',' комментария',' комментариев')
    	);
    	
    	/* вариант 5 */
    	$var5 = get_decline_string(
    		/* варианты написания префикса для количества 1, 2 и 5 */
    		array('опубликован: ','опубликовано: ','опубликовано: '),
    		/* число */
    		$comments,
    		/* суффикс */
    		null
    	);
    	
    	/* вариант 6 */
    	$var6 = get_decline(
    		/* число */
    		$comments,
    		/* суффикс */
    		array('комментарий','комментария','комментариев')
    	);
    	
    	/* вариант 7 */
    	$var7 = get_decline_string(
    		/* варианты написания префикса для количества 1, 2 и 5 */
    		array('опубликован ','опубликовано ','опубликовано '),
    		/* число */
    		$comments,
    		/* варианты написания суффикса для количества 1, 2 и 5 */
    		array(' комментарий',' комментария',' комментариев'),
    		/* вывести как массив */
    		true
    	);
    ?>
    

    Вывод:

    <?php
    	echo $var1 . '<br /&amp;gt';
    	echo $var2 . '<br /&amp;gt';
    	echo $var3 . '<br /&amp;gt';
    	echo $var4 . '<br /&amp;gt';
    	echo $var5 . '<br /&amp;gt';
    	echo $var6 . '<br /&amp;gt';
    	echo '<pre>' . print_r($var7, true) . '

    ‘;
    ?>

    Результат:

    опубликовано 5 комментариев<br />
    опубликовано: 5 комментариев<br />
    опубликовано: 5 комм.<br />
    5 комментариев<br />
    опубликовано: 5<br />
    комментариев<br />
    
    Array
    	(
    		[prefix] => опубликовано 
    		[value] => 5
    		[suffix] => комментариев
    	)
    

    Спасибо за внимание.

  10. 18
    @

    Вот спасибочки. Это мне точно пригодится.

Ваш комментарий