Drupal

индекс
142,25

Патч к Drupal-модулю Date — показываем месяцы в родительном падеже

Вывод даты в виде "27 февраль 2010" это уродливо. Ни в русском, ни в украинском, ни в польском — и, я думаю, что это касается большинства других славянских языков — так не говорят и не пишут.

НЕправильные даты в выводе ноды

Понятно, что через какое-то время привыкаешь и просто не замечаешь, но есть ведь настойчивые заказчики, которые тыкают носом разработчика в эти «ляпы» и требующие исправления ошибок (по их мнению). Спасибо им за это. Это нужно, хотя и раздражает.


Вывод блока с кастомным обработчиком дат.



Итак, по требованию заказчика вывести в блоке нормальные даты я написал модуль. Модуль выводит блок, где определённым образом форматируется вывод анонсов и собственно исправляются даты. Точно такой же блок можно сделать во Views, если бы не кривые даты…

Короче говоря код модуля я приводить не буду, а только функцию, которая исправляет даты. Этот код может очень пригодится тем, кто не сможет дочитать пост до конца.

Ок. Код всего модуля приложен к статье, чтобы уменьшить соотношение код/текст, чтобы не объяснять как делается вызов фунции и в каком формате должна быть дата — изучайте сами, если это вам нужно. Даты начала события и конца хранятся в одном ССК-поле, которое называется field_event_date и имеет тип Date.

Но этот модуль можно не использовать, а применить патч для модуля Date, но об этом ниже.

  1. // Функция преобразует даты в "правильные", то есть в родительном падеже и ещё разные штучки делает.
  2. function _calendar_list_conv_date($a, $format='front') {
  3.   global $language;
  4.   $date = strtotime($a);
  5.   switch($format) {
  6.     case 'front':
  7.       $monthes = array (
  8.         'en' => array('January','February','March','April','May','June','July','August','September','October','November','December'),
  9.         'ru' => array('января','февраля','марта','апреля','мая','июня','июля','августа','сентября','октября','ноября','декабря'),
  10.         'uk' => array('січня','лютого','березня','квітня','травня','червня','липня','серпня','вересня','жовтня','листопада','грудня'),
  11.       );
  12.       $weekday = array (
  13.         'en' => array('Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'),
  14.         'ru' => array('Понедельник','Вторник','Среда','Четверг','Пятница','Суббота','Воскресенье'),
  15.         'uk' => array('Понеділок','Вівторок','Середа','Четвер','П’ятниця','Субота','Неділя'),
  16.       );
  17.       switch ($language->language) {
  18.         case 'ru':
  19.         case 'uk':
  20.             $output = date("j",$date) .' '. $monthes[$language->language][date("n",$date)-1] .', '. $weekday[$language->language][date("N",$date)-1];
  21.             break;
  22.         case 'en':
  23.         default:
  24.             $output = $monthes[$language->language][date("n",$date)-1] .' '. date("j",$date) .', '. $weekday[$language->language][date("N",$date)-1];
  25.             break;
  26.       }
  27.  
  28.       break;
  29.     case 'short':
  30.       $output = date('d.m.Y', $date); //20.02.2010
  31.       break;
  32.     default:
  33.       $output = date("j",$date).' '.$monthes[date("n",$date)-1].' '.date("Y",$date).' '.date("H",$date).':'.date("i",$date);
  34.       break;
  35.   }
  36.   return $output;
  37. }


После созерцания блока с «хорошими» датами заказчик успокоился и потребовал сделать «правильно» в остальных местах сайта…

Я понял, что нужно кардинально другое решение — универсальное и системное. Очень много времени ушло на то, чтобы понять какой именно модуль и как меняет даты — возможно сказалось то, что температура была большая.
Сам код решения был написан и оттестирован где-то за полдня.

Исправленные даты - месяц в родительном падеже

Патч модуля Date, чтобы получить корректную обработку дат для всего сайта



Изменяются только 3 функции в файле date_api.module модуля Date:
  • date_t
  • date_t_strings
  • date_format_date


Идея в том, что название месяца в родительном падеже должно выводиться только, если выводится рядом с числом месяца. Во всех остальных случаях — именительный падеж.

Пример:


23 февраля 2010, а не 23 февраль 2010.
Но март 2010, а не марта 2010

Как заставить все это работать?


  • Применить патч, который приложен к статье или скопировать уже изменённые функции вместо старых. Рецепт о том, как применить патч (есть варианты для Линукс, и для Винды): Применение заплат (patch)
  • Открыть страницу "Перевод интерфейса" (admin/build/translate/search) и найти строку:
    !month-genitive |January|February|March|April|May|June|July|August|September|October|November|December
  • Сделать её перевод на нужный язык. Учтите, что для английского названия месяцев обычно пишутся с заглавной, а у нас — нет. Названия
    месяцев должны быть в родильном падеже. Для русского и украинского языков это выглядит так:
    • Русский:
      !month-genitive |января|февраля|марта|апреля|мая|июня|июля|августа|сентября|октября|ноября|декабря
    • Украинский:
      !month-genitive |січня|лютого|березня|квітня|травня|червня|липня|серпня|вересня|жовтня|листопада|грудня

  • Сохранить переводы и проверить отображение дат.


Будущее патча


Все эти манипуляции (применение патча и перевод вручную строк) нужно делать только пока патч не будет принят разработчиками модуля Date и не выпущен релиз с этими изменениями.
Пока я не вижу причин, которые могут припятствовать, но всякое бывает и, даже, если патч будет принят, то дата выхода релиза может отодвигаться по другим причинам.

Англоязычным товарищам этот патч не нужен, потому что в английском языке этой проблемы с датами нет и они могут счесть его не важным, поэтому я попробую опубликовать эту же статью на хабре и прошу поддержать также issue с патчем на drupal.org:

drupal.org/node/728350 — Multilanguage month support

Скачать:
  1. Модуль Calendar List — выводит блоки со списками событий и правильной датой
  2. Патч для модуля Date
+27
28 февраля 2010, 19:47
38

комментарии (31)

+2
khizhaster #
1. Либо в соответствующий блог, либо укажите название продукта.
2. Оформите код с помощью какого-нибудь редактора с подсветкой.
+7
UUSER #
Афигенно… то что это относится к Drupal'у можно узнать только из комментария в коде.
0
VladSavitsky #
У меня не хватило кармы опубликовать в тематическом блоге. Увы.
0
tass #
ну дак хоть укажите в названии статьи что для друпала
+1
VladSavitsky #
Уже указал в заголовке, что речь идёт о Drupal и сделал подсветку синтаксиса. Спасибо за замечания.
0
brmn #
use theme functions.
и будет Вам счастье ;)
0
VladSavitsky #
Как именно это можно использовать?
+2
ChemAli #
Он, видимо, предлагает перекрывать переменные $submitted и т.п. Я обычно в template.php определяю свою функцию вывода времени и использую ее в *.tpl.php. Предпочитаю даты вида
«понедельник, 8 марта 2010 года в 16:30» (длинный формат), «8 марта в 16:30» (короткий для текущего года) и т.п.
+1
zibada #
8 марта, Понедельник — это столь же не по-русски, как и 8 Март, Понедельник.
0
StopDesign #
Чтобы написать действительно по-русски, нужно еще 5 лет и 200 килобайт кода.
0
ChemAli #
На «понедельник 8 марта» вам нужно 5 лет? :)
0
Anonym #
Патчить модули — это моветон.
Идем в admin/build/translate/search, находим нужные строки и переводим как нам нравится.
–1
VladSavitsky #
Вы предлагаете то, что сами не пробовали. А я этот вариант проверил — результат плохой.
Почему? Потому что исправляя перевод названий месяцев мы получаем родительный падеж ВЕЗДЕ, что не верно. То есть «марта, 2010» в блоке календаря и прочее.
Поэтому это не вариант.
–4
Anonym #
Сам пробовал. Если переводить не всё подряд, а только нужные строки, то несовпадений практически нет
0
Washington #
да полно совпадений. напереводились в свое время, не надо лял-я :)
0
Washington #
*ля-ля :))))
0
Anonym #
Ну Вам конечно же виднее.
0
sadmin #
Не все так просто, одному слову может соответствовать несколько переводов
+1
Valeratal #
я тупо, использую короткий формат даты

В конце концов, через пару лет, какая разница в какой день недели была опубликована конкретная нода.

Хотя не спорю, где то это нужно
+1
DRUN #
Извиняюсь, но хочу вставить свои пять копеек.
Быть может это очень глупо и не правильно, но иногда, когда я заполняю документы(благо это не президентские рукописи)) и там прописаны графы типа "__/_____/20__" то я пишу «08/март/2010» или даже такие «08 _______ 20__» тоже, заполняя, пишу месяц в именительном падеже.

Поэтому, лично мое мнение, менять падеж только основываясь на том, что перед месяцем стоит цифра — неверно. Видится мне, что куда сложнее потом будет избавиться от неверно всплывшем падеже, в каком-нибудь закадычном месте. Уж если менять падеж, то только указывая где-то в параметрах функции в какой именно падеж вам хочется привести слово.
0
bobrik #
уважаемый, вы как вообще планируете определять необходимость наличия падежа для любого языка? кто вам вообще сказал, что в текущем языке будет падеж и что он будет родительный? вы как бы не забывайте, что машина воображение включать не будет на этот счёт
+2
alexxxst #
UK — Украина? Жостко…
+1
vladon #
uk = украинский язык (ISO-639-1)

очевидно, что здесь не страны, а языки.
0
pvasili #
ГОСТ суров — но он ISO :)
Хорошо, что сократили до 1, а то какое то время на drupal.org было 2 варианта…
0
mifa #
Патч к модулю… Вот по этому я перестал использовать друпал. Хотя, в своей нише, наверное, он лучший.
0
taldy #
Ну не знаю. Тот патч который стоит не любить (который приходится самому поддерживать) мне кажется достаточно редкое явление в Друпале. В подавляющем большинстве случаев сделанный патч отправляется разработчику модуля и уже в следующей версии этого модуля вы получаете решение вашей проблемы и следовательно при обновлении ваш код можно не поддерживать, в модуле эта функциональность уже есть. Это по сути не патч, это ваша «помощь комьюнити». Патчи, которые по каким-то причинам не включаются в модуля — достаточно редкое явление.
+1
VladSavitsky #
Это точно. Патч в данном случае это название программы (patch), которая используется, чтобы наложить изменения на текущий код модуля. И кроме того, акцент на слове патч как раз и значит, что вероятность его принятия разработчиком модуля очень велика — я всё уже подготовил.

Если бы я в вольной форме изложил автору модуля чего я хочу и просил бы его самого это сделать, но это было бы реально дольше и называлось бы не патч, а feature request. И их там тысячи.

С выходом 7ки к патчам будут предьявляться всё более жесткие требования (код должен проходить автоматизированные тесты), но я считаю, что с ростом сложности системы это просто необходимо и очень разумно. Но это касается ядра Друпал. Какая-то другая CMS может похвастаться автоматизированными тестами для своего ядра?!
–2
ajvol #
А нужно ли где-нибудь выводить названия месяцев в именительном падеже? Было бы проще изменить все переводв на родительный падеж, в своё время так было сделано при локализации MediaWiki.
0
VladSavitsky #
К сожалению нужно. Модуль Calendar, например, выводит разного рода списки где есть архив по месяцам (март 2010, апрель 2010). Есть блок с календарём, где в заголовке название месяца и, если оно в родительном падеже, но это выглядит не очень…
0
edhell #
Я для подобных вещей написал функцию format_date2 и везде в шаблонах и своих модулях использую ее, вместо стандартной format_date.

global $_format_date2_monthes;

$_format_date2_monthes['large']['ru'] = array('', 'января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря');
$_format_date2_monthes['large']['en'] = array('', 'january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december');
$_format_date2_monthes['medium']['ru'] = array('', 'янв', 'фев', 'мар', 'апр', 'мая', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек');
$_format_date2_monthes['medium']['en'] = array('', 'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec');

// type=[small,medium,large], language=[ru,en,cn,es,de]
function format_date2($timestamp, $type = 'medium', $language = NULL) {
if (empty($language)) $language = $GLOBALS['language']->language;
if ($language == 'zh-hans') return date('Y年m月d日', $timestamp);
$small = date('d.m.Y', $timestamp);
if ($type == 'small') return $small;
global $_format_date2_monthes;
list($day, $month, $year) = explode(".", $small);
$day = (int) $day; $month = (int) $month; $year = (int) $year;
$month = $_format_date2_monthes[$type][$language][$month];
if (empty($month)) return $small;
$result = "$day $month $year";
if ($language == 'ru') $result .= " г.";
return $result;
}
0
VladSavitsky #
Патч на drupal.org до сих пор не закоммитили. Автор модуля хочет, чтобы его больше людей потестили и желательно не на русскоязычных/англоязычных сайтах.
Поэтому если кто имеет подобные сайты и использует патч — отпишитесь в drupal.org/node/728350

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.