Русификация Octopress

17 сентября 2015. Комментарии .

В интернете есть несколько записей о русификации дат в Octopress, например, на сегодня доступны Rinat’s Blog и maximmikheev.ru. Забавно, что оба они ссылаются на одного и того же немца. Просто повторяться я бы, конечно, не стал, однако упомянутые записи написаны более 3-х лет назад (24 мая и 13 июля 2012 соответственно), за это время время Jekyll обновился и перестал работать с некоторыми конструкциями из ruby. Мне удалось разобраться, как с этим бороться, о чём и расскажу.

Датами управляет плагин plugins/date.rb. Приведите его к такому виду:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# encoding: utf-8
module Octopress
module Date
# Русская локализация:
MONTHNAMES_RU = [nil, "Января", "Февраля", "Марта", "Апреля", "Мая", "Июня", "Июля", "Августа", "Сентября", "Октября", "Ноября", "Декабря" ]
ABBR_MONTHNAMES_RU = [nil, "Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек" ]
DAYNAMES_RU = [ "Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота" ]
ABBR_DAYNAMES_RU = [ "Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб" ]

# Returns a datetime if the input is a string
def datetime(date)
if date.class == String
date = Time.parse(date)
end
date
end

# В _config.yml должно быть задано: date_format: ordinal
def ordinalize(date)
# Задаем наш формат выдачи даты
format_date(date, "%d %b %Y") # 20 Авг 2019
end

# Formats date either as ordinal or by given date format
# Adds %o as ordinal representation of the day
def format_date(date, format)
date = datetime(date)
if format.nil? || format.empty? || format == "ordinal"
date_formatted = ordinalize(date)
else
format.gsub!(/%a/, ABBR_DAYNAMES_RU[date.wday])
format.gsub!(/%A/, DAYNAMES_RU[date.wday])
format.gsub!(/%b/, ABBR_MONTHNAMES_RU[date.mon])
format.gsub!(/%B/, MONTHNAMES_RU[date.mon])
date_formatted = date.strftime(format)
end
date_formatted
end

end
end

module Jekyll

class Post
include Octopress::Date

def to_liquid(attrs = nil)
date_format = self.site.config['date_format']
new_datas = {
"title" => self.data['title'] || self.slug.split('-').select {|w| w.capitalize! || w }.join(' '),
"url" => self.url,
"date" => self.date,
# Monkey patch
"date_formatted" => format_date(self.date, date_format),
"updated_formatted" => self.data.has_key?('updated') ? format_date(self.data['updated'], date_format) : nil,
"id" => self.id,
"categories" => self.categories,
"next" => self.next,
"previous" => self.previous,
"tags" => self.tags,
"content" => self.content }
Utils.deep_merge_hashes(self.data, new_datas)
end
end

class Page
include Octopress::Date

# Initialize a new Page.
#
# site - The Site object.
# base - The String path to the source.
# dir - The String path between the source and the file.
# name - The String filename of the file.
def initialize(site, base, dir, name)
@site = site
@base = base
@dir = dir
@name = name

self.process(name)
self.read_yaml(File.join(base, dir), name)
# Monkey patch
date_format = self.site.config['date_format']
self.data['date_formatted'] = format_date(self.data['date'], date_format) if self.data.has_key?('date')
self.data['updated_formatted'] = format_date(self.data['updated'], date_format) if self.data.has_key?('updated')
end
end

module Filters
include Octopress::Date
def date_ru(date, format)
format_date(date, format)
end
end

end

Отличие от процитированных записей здесь в строках 48–65: там используется deep_merge, на который Jekyll старше 2.0 ругается. Оказалось, что его нужно заменить на Utils.deep_merge_hashes. Я так и не смог проделать это самостоятельно (обожаю ruby!), но мне ответили на stackoverflow.

В _config.yml укажите:

date_format: "ordinal"

Менять формат вывода даты надо в самом date.rb в строке №21. Подробнее о форматировании даты см. на ruby-doc.

Сразу же после изменения date.rb попробуйте собрать блог: rake generate. Даты пока не изменятся, просто проверьте, что всё собирается. Теперь нам осталось заменить в некоторых файлах date на date_ru. Переменная date может встречаться в разных файлах в зависимости от темы. Обычно она находится в source/_includes/archive_post.html. В теме Octostrap3, например, она встречается 7 раз в source/_includes/post/date.html. После замены файл выглядит так:

source/_includes/post/date.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{% capture date_ru %}{{ page.date }}{{ post.date }}{% endcapture %}
{% capture date_formatted %}{% if page.date %}{{ page.date | date_ru: site.date_format }}{% endif %}{% if post.date %}{{ post.date | date_ru: site.date_format }}{% endif %}{% endcapture %}
{% capture has_date %}{{ date_ru | size }}{% endcapture %}

{% capture updated %}{{ page.updated }}{{ post.updated }}{% endcapture %}
{% capture updated_formatted %}{% if page.updated %}{{ page.updated | date_ru: site.date_format }}{% endif %}{% if post.updated %}{{ post.updated | date_ru: site.date_format }}{% endif %}{% endcapture %}
{% capture was_updated %}{{ updated | size }}{% endcapture %}

{% if has_date != '0' %}
{% capture time %}<span class="glyphicon glyphicon-calendar"></span> <time datetime="{{ date_ru | datetime | date_to_xmlschema }}" {% if updated %} data-updated="true"{% endif %} itemprop="datePublished dateCreated">{{ date_formatted }}</time>{% endcapture %}
{% endif %}

{% if was_updated != '0' %}
{% capture updated %}<span class="glyphicon glyphicon-calendar"></span> <time datetime="{{ updated | datetime | date_to_xmlschema }}" class="updated" itemprop="dateModified">Updated {{ updated_formatted }}</time>{% endcapture %}
{% else %}{% assign updated = false %}{% endif %}

В процитированных блогах указан такой вариант:

source/_includes/archive_post.html
1
2
3
4
5
6
7
8
9
10

{% capture category %}{{ post.categories | size }}{% endcapture %}
<h1><a href="{{ root_url }}{{ post.url }}">{{post.title}}</a></h1>
<time datetime="{{ post.date | datetime | date_to_xmlschema }}" pubdate>{{ post.date | date_ru: "<span class='day'>%d</span> <span class='month'>%b</span> <span class='year'>%Y</span>"}}</time>
{% if category != '0' %}
<footer>
<span class="categories">Опубликовано в {{ post.categories | category_links }}</span>
</footer>
{% endif %}

Но ещё раз повторю, всё зависит от темы. Обратите внимание: менять на date_ru нужно только отдельно стоящее date, а post.date, например, трогать не надо.

А чтобы найти фразы типа «Posted by, Comments, Recent Posts, Categories, Previous post» и т.д., воспользуйтесь командой

grep -irl 'posted by' /path/to/octopress/source

Затем вручную редактируйте найденные файлы. Или можно делать замены с помощью потокового редактора sed, например (сделайте backup сначала):

find /path/to/octopress/source -type f -exec sed -i 's:recent posts:Последние записи:gI' {} +

Флаг -i означает менять оригинальный файл, s — замена, далее через двоеточие что и на что менять, g — менять все вхождения в строке, I — нечувствительно к регистру.

Вот и всё, Октопресс локализован. Если что-то не сработало, обязательно дайте знать в комментариях.