russian 0.2.7 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +24 -0
- data/Gemfile +9 -0
- data/LICENSE +1 -1
- data/README.textile +136 -139
- data/Rakefile +4 -49
- data/TODO +0 -6
- data/lib/russian.rb +18 -39
- data/lib/russian/action_view_ext/helpers/date_helper.rb +15 -9
- data/lib/russian/active_model_ext/custom_error_message.rb +70 -0
- data/lib/russian/locale/actionview.yml +100 -50
- data/lib/russian/locale/activemodel.yml +50 -0
- data/lib/russian/locale/activerecord.yml +24 -24
- data/lib/russian/locale/datetime.rb +39 -0
- data/lib/russian/locale/datetime.yml +9 -5
- data/lib/russian/locale/pluralization.rb +28 -0
- data/lib/russian/locale/transliterator.rb +17 -0
- data/lib/russian/russian_rails.rb +8 -0
- data/lib/russian/version.rb +9 -0
- data/russian.gemspec +26 -0
- data/spec/locale_spec.rb +5 -87
- data/spec/russian_spec.rb +5 -23
- metadata +70 -69
- data/init.rb +0 -3
- data/lib/russian/active_record_ext/custom_error_message.rb +0 -163
- data/lib/russian/active_support_ext/parameterize.rb +0 -31
- data/lib/russian/backend/advanced.rb +0 -134
- data/lib/russian/locale/pluralize.rb +0 -25
- data/lib/vendor/i18n/MIT-LICENSE +0 -20
- data/lib/vendor/i18n/README.textile +0 -20
- data/lib/vendor/i18n/Rakefile +0 -5
- data/lib/vendor/i18n/i18n.gemspec +0 -27
- data/lib/vendor/i18n/lib/i18n.rb +0 -199
- data/lib/vendor/i18n/lib/i18n/backend/simple.rb +0 -214
- data/lib/vendor/i18n/lib/i18n/exceptions.rb +0 -53
- data/lib/vendor/i18n/test/all.rb +0 -5
- data/lib/vendor/i18n/test/i18n_exceptions_test.rb +0 -100
- data/lib/vendor/i18n/test/i18n_test.rb +0 -125
- data/lib/vendor/i18n/test/locale/en.rb +0 -1
- data/lib/vendor/i18n/test/locale/en.yml +0 -3
- data/lib/vendor/i18n/test/simple_backend_test.rb +0 -568
- data/lib/vendor/i18n_label/README.textile +0 -38
- data/lib/vendor/i18n_label/Rakefile +0 -11
- data/lib/vendor/i18n_label/init.rb +0 -1
- data/lib/vendor/i18n_label/install.rb +0 -1
- data/lib/vendor/i18n_label/lib/i18n_label.rb +0 -23
- data/lib/vendor/i18n_label/spec/i18n_label_spec.rb +0 -20
- data/lib/vendor/i18n_label/spec/spec_helper.rb +0 -10
- data/lib/vendor/i18n_label/tasks/i18n_label_tasks.rake +0 -4
- data/lib/vendor/i18n_label/uninstall.rb +0 -1
data/TODO
CHANGED
@@ -1,10 +1,4 @@
|
|
1
1
|
TODO
|
2
2
|
====
|
3
3
|
* RDoc
|
4
|
-
* check Unicode CLDR to ensure all datetime formats are correct
|
5
|
-
* refactor Advanced backend localize method (looks ugly)
|
6
|
-
* refactor DateTimeSelector#translated_month_names
|
7
4
|
|
8
|
-
Questionable
|
9
|
-
============
|
10
|
-
* integration specs for rails hacks
|
data/lib/russian.rb
CHANGED
@@ -1,38 +1,16 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
|
-
if RUBY_VERSION < "1.9"
|
4
|
-
$KCODE = 'u'
|
5
|
-
end
|
6
|
-
|
7
|
-
$:.push File.join(File.dirname(__FILE__), 'russian')
|
8
|
-
require 'transliteration'
|
3
|
+
$KCODE = 'u' if RUBY_VERSION < "1.9"
|
9
4
|
|
10
|
-
|
11
|
-
unless defined?(I18n)
|
12
|
-
$:.push File.join(File.dirname(__FILE__), 'vendor', 'i18n', 'lib')
|
13
|
-
require 'i18n'
|
14
|
-
end
|
15
|
-
# Advanced backend
|
16
|
-
require 'backend/advanced'
|
5
|
+
require 'i18n'
|
17
6
|
|
18
|
-
|
19
|
-
require '
|
20
|
-
if defined?(ActionView::Helpers)
|
21
|
-
require 'action_view_ext/helpers/date_helper'
|
22
|
-
require 'vendor/i18n_label/init'
|
23
|
-
end
|
24
|
-
require 'active_support_ext/parameterize' if defined?(ActiveSupport::Inflector)
|
7
|
+
$:.push File.join(File.dirname(__FILE__), 'russian')
|
8
|
+
require 'russian_rails'
|
25
9
|
|
26
10
|
module Russian
|
27
11
|
extend self
|
28
12
|
|
29
|
-
|
30
|
-
MAJOR = 0
|
31
|
-
MINOR = 2
|
32
|
-
TINY = 7
|
33
|
-
|
34
|
-
STRING = [MAJOR, MINOR, TINY].join('.')
|
35
|
-
end
|
13
|
+
autoload :Transliteration, 'transliteration'
|
36
14
|
|
37
15
|
# Russian locale
|
38
16
|
LOCALE = :'ru'
|
@@ -41,20 +19,21 @@ module Russian
|
|
41
19
|
def locale
|
42
20
|
LOCALE
|
43
21
|
end
|
44
|
-
|
45
|
-
#
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
# Init Russian i18n: set custom backend, set default locale to Russian locale, load all translations
|
53
|
-
# shipped with library.
|
22
|
+
|
23
|
+
# Regexp machers for context-based russian month names and day names translation
|
24
|
+
LOCALIZE_ABBR_MONTH_NAMES_MATCH = /(%d|%e)(.*)(%b)/
|
25
|
+
LOCALIZE_MONTH_NAMES_MATCH = /(%d|%e)(.*)(%B)/
|
26
|
+
LOCALIZE_STANDALONE_ABBR_DAY_NAMES_MATCH = /^%a/
|
27
|
+
LOCALIZE_STANDALONE_DAY_NAMES_MATCH = /^%A/
|
28
|
+
|
29
|
+
# Init Russian i18n: load all translations shipped with library.
|
54
30
|
def init_i18n
|
55
|
-
I18n.
|
56
|
-
I18n.
|
31
|
+
I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)
|
32
|
+
I18n::Backend::Simple.send(:include, I18n::Backend::Transliterator)
|
33
|
+
|
57
34
|
I18n.load_path.unshift(*locale_files)
|
35
|
+
|
36
|
+
I18n.reload!
|
58
37
|
end
|
59
38
|
|
60
39
|
# See I18n::translate
|
@@ -17,7 +17,7 @@
|
|
17
17
|
# All date helpers support <tt>:use_standalone_month_names</tt> key now, <tt>select_month</tt> helper sets
|
18
18
|
# it to true by default.
|
19
19
|
# Standalone month names are also used when <tt>:discard_day</tt> key is provided.
|
20
|
-
if defined?(ActionView::Helpers::DateTimeSelector)
|
20
|
+
if defined?(ActionView::Helpers::DateTimeSelector)
|
21
21
|
module ActionView
|
22
22
|
module Helpers
|
23
23
|
module DateHelper
|
@@ -87,23 +87,29 @@ if defined?(ActionView::Helpers::DateTimeSelector) && ActionView::Helpers::DateT
|
|
87
87
|
# убеждается, есть ли соотвествующие переводы в текущем языке и использует "отдельностоящие" названия
|
88
88
|
# месяцев по необходимости
|
89
89
|
def translated_month_names
|
90
|
-
|
91
|
-
if
|
92
|
-
if (@options[:discard_day] || @options[:use_standalone_month_names])
|
90
|
+
if @options[:use_short_month]
|
91
|
+
if I18n.backend.send(:lookup, I18n.locale, :'date.common_abbr_month_names')
|
92
|
+
if (@options[:discard_day] || @options[:use_standalone_month_names])
|
93
93
|
key = :'date.standalone_abbr_month_names'
|
94
94
|
else
|
95
|
-
key = :'date.
|
95
|
+
key = :'date.common_abbr_month_names'
|
96
96
|
end
|
97
97
|
else
|
98
|
-
|
98
|
+
key = :'date.abbr_month_names'
|
99
|
+
end
|
100
|
+
else
|
101
|
+
if I18n.backend.send(:lookup, I18n.locale, :'date.common_month_names')
|
102
|
+
if (@options[:discard_day] || @options[:use_standalone_month_names])
|
99
103
|
key = :'date.standalone_month_names'
|
100
104
|
else
|
101
|
-
key = :'date.
|
105
|
+
key = :'date.common_month_names'
|
102
106
|
end
|
107
|
+
else
|
108
|
+
key = :'date.month_names'
|
103
109
|
end
|
104
|
-
|
105
|
-
I18n.translate(key, :locale => @options[:locale])
|
106
110
|
end
|
111
|
+
|
112
|
+
I18n.translate(key, :locale => @options[:locale])
|
107
113
|
end
|
108
114
|
|
109
115
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
if defined?(ActiveModel::Errors)
|
4
|
+
module ActiveModel
|
5
|
+
class Errors
|
6
|
+
# Redefine the ActiveModel::Errors.full_messages method:
|
7
|
+
# Returns all the full error messages in an array. 'Base' messages are handled as usual.
|
8
|
+
# Non-base messages are prefixed with the attribute name as usual UNLESS they begin with '^'
|
9
|
+
# in which case the attribute name is omitted.
|
10
|
+
# E.g. validates_acceptance_of :accepted_terms, :message => '^Please accept the terms of service'
|
11
|
+
#
|
12
|
+
# Переопределяет метод ActiveModel::Errors.full_messages. Сообщения об ошибках для атрибутов
|
13
|
+
# теперь не имеют префикса с названием атрибута если в сообщении об ошибке первым символом указан "^".
|
14
|
+
#
|
15
|
+
# Так, например,
|
16
|
+
#
|
17
|
+
# validates_acceptance_of :accepted_terms, :message => 'нужно принять соглашение'
|
18
|
+
#
|
19
|
+
# даст сообщение
|
20
|
+
#
|
21
|
+
# Accepted terms нужно принять соглашение
|
22
|
+
#
|
23
|
+
# однако,
|
24
|
+
#
|
25
|
+
# validates_acceptance_of :accepted_terms, :message => '^Нужно принять соглашение'
|
26
|
+
#
|
27
|
+
# даст сообщение
|
28
|
+
#
|
29
|
+
# Нужно принять соглашение
|
30
|
+
#
|
31
|
+
#
|
32
|
+
# Returns all the full error messages in an array.
|
33
|
+
#
|
34
|
+
# class Company
|
35
|
+
# validates_presence_of :name, :address, :email
|
36
|
+
# validates_length_of :name, :in => 5..30
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# company = Company.create(:address => '123 First St.')
|
40
|
+
# company.errors.full_messages # =>
|
41
|
+
# ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Address can't be blank"]
|
42
|
+
def full_messages
|
43
|
+
full_messages = []
|
44
|
+
|
45
|
+
each do |attribute, messages|
|
46
|
+
messages = Array.wrap(messages)
|
47
|
+
next if messages.empty?
|
48
|
+
|
49
|
+
if attribute == :base
|
50
|
+
messages.each {|m| full_messages << m }
|
51
|
+
else
|
52
|
+
attr_name = attribute.to_s.gsub('.', '_').humanize
|
53
|
+
attr_name = @base.class.human_attribute_name(attribute, :default => attr_name)
|
54
|
+
options = { :attribute => attr_name, :default => "%{attribute} %{message}" }
|
55
|
+
|
56
|
+
messages.each do |m|
|
57
|
+
if m =~ /^\^/
|
58
|
+
full_messages << m[1..-1]
|
59
|
+
else
|
60
|
+
full_messages << I18n.t(:"errors.format", options.merge(:message => m))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
full_messages
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end # if defined?
|
@@ -12,6 +12,8 @@ ru:
|
|
12
12
|
delimiter: " "
|
13
13
|
# Number of decimals, behind the separator (the number 1 with a precision of 2 gives: 1.00)
|
14
14
|
precision: 3
|
15
|
+
significant: false
|
16
|
+
strip_insignificant_zeros: false
|
15
17
|
|
16
18
|
# Used in number_to_currency()
|
17
19
|
currency:
|
@@ -26,6 +28,8 @@ ru:
|
|
26
28
|
separator: "."
|
27
29
|
delimiter: " "
|
28
30
|
precision: 2
|
31
|
+
significant: false
|
32
|
+
strip_insignificant_zeros: false
|
29
33
|
|
30
34
|
# Used in number_to_percentage()
|
31
35
|
percentage:
|
@@ -49,11 +53,13 @@ ru:
|
|
49
53
|
# separator:
|
50
54
|
delimiter: ""
|
51
55
|
precision: 1
|
56
|
+
significant: false
|
57
|
+
strip_insignificant_zeros: false
|
52
58
|
|
53
59
|
# Rails 2.2
|
54
60
|
# storage_units: [байт, КБ, МБ, ГБ, ТБ]
|
55
61
|
|
56
|
-
# Rails 2.3
|
62
|
+
# Rails 2.3+
|
57
63
|
storage_units:
|
58
64
|
# Storage units output formatting.
|
59
65
|
# %u is the storage unit, %n is the number (default: 2 MB)
|
@@ -69,6 +75,36 @@ ru:
|
|
69
75
|
gb: "ГБ"
|
70
76
|
tb: "ТБ"
|
71
77
|
|
78
|
+
decimal_units:
|
79
|
+
format: "%n %u"
|
80
|
+
units:
|
81
|
+
unit: ""
|
82
|
+
thousand:
|
83
|
+
one: "тысяча"
|
84
|
+
few: "тысяч"
|
85
|
+
many: "тысяч"
|
86
|
+
other: "тысяч"
|
87
|
+
million:
|
88
|
+
one: "миллион"
|
89
|
+
few: "миллионов"
|
90
|
+
many: "миллионов"
|
91
|
+
other: "миллионов"
|
92
|
+
billion:
|
93
|
+
one: "миллиард"
|
94
|
+
few: "миллиардов"
|
95
|
+
many: "миллиардов"
|
96
|
+
other: "миллиардов"
|
97
|
+
trillion:
|
98
|
+
one: "триллион"
|
99
|
+
few: "триллионов"
|
100
|
+
many: "триллионов"
|
101
|
+
other: "триллионов"
|
102
|
+
quadrillion:
|
103
|
+
one: "квадриллион"
|
104
|
+
few: "квадриллионов"
|
105
|
+
many: "квадриллионов"
|
106
|
+
other: "квадриллионов"
|
107
|
+
|
72
108
|
# Используется в хелперах distance_of_time_in_words(), distance_of_time_in_words_to_now(), time_ago_in_words()
|
73
109
|
#
|
74
110
|
#
|
@@ -77,60 +113,61 @@ ru:
|
|
77
113
|
distance_in_words:
|
78
114
|
half_a_minute: "меньше минуты"
|
79
115
|
less_than_x_seconds:
|
80
|
-
one: "меньше {
|
81
|
-
few: "меньше {
|
82
|
-
many: "меньше {
|
83
|
-
other: "меньше {
|
116
|
+
one: "меньше %{count} секунды"
|
117
|
+
few: "меньше %{count} секунд"
|
118
|
+
many: "меньше %{count} секунд"
|
119
|
+
other: "меньше %{count} секунды"
|
84
120
|
x_seconds:
|
85
|
-
one: "{
|
86
|
-
few: "{
|
87
|
-
many: "{
|
88
|
-
other: "{
|
121
|
+
one: "%{count} секунда"
|
122
|
+
few: "%{count} секунды"
|
123
|
+
many: "%{count} секунд"
|
124
|
+
other: "%{count} секунды"
|
89
125
|
less_than_x_minutes:
|
90
|
-
one: "меньше {
|
91
|
-
few: "меньше {
|
92
|
-
many: "меньше {
|
93
|
-
other: "меньше {
|
126
|
+
one: "меньше %{count} минуты"
|
127
|
+
few: "меньше %{count} минут"
|
128
|
+
many: "меньше %{count} минут"
|
129
|
+
other: "меньше %{count} минуты"
|
94
130
|
x_minutes:
|
95
|
-
one: "{
|
96
|
-
few: "{
|
97
|
-
many: "{
|
98
|
-
other: "{
|
131
|
+
one: "%{count} минута"
|
132
|
+
few: "%{count} минуты"
|
133
|
+
many: "%{count} минут"
|
134
|
+
other: "%{count} минуты"
|
99
135
|
about_x_hours:
|
100
|
-
one: "около {
|
101
|
-
few: "около {
|
102
|
-
many: "около {
|
103
|
-
other: "около {
|
136
|
+
one: "около %{count} часа"
|
137
|
+
few: "около %{count} часов"
|
138
|
+
many: "около %{count} часов"
|
139
|
+
other: "около %{count} часа"
|
104
140
|
x_days:
|
105
|
-
one: "{
|
106
|
-
few: "{
|
107
|
-
many: "{
|
108
|
-
other: "{
|
141
|
+
one: "%{count} день"
|
142
|
+
few: "%{count} дня"
|
143
|
+
many: "%{count} дней"
|
144
|
+
other: "%{count} дня"
|
109
145
|
about_x_months:
|
110
|
-
one: "около {
|
111
|
-
few: "около {
|
112
|
-
many: "около {
|
113
|
-
other: "около {
|
146
|
+
one: "около %{count} месяца"
|
147
|
+
few: "около %{count} месяцев"
|
148
|
+
many: "около %{count} месяцев"
|
149
|
+
other: "около %{count} месяца"
|
114
150
|
x_months:
|
115
|
-
one: "{
|
116
|
-
few: "{
|
117
|
-
many: "{
|
118
|
-
other: "{
|
151
|
+
one: "%{count} месяц"
|
152
|
+
few: "%{count} месяца"
|
153
|
+
many: "%{count} месяцев"
|
154
|
+
other: "%{count} месяца"
|
119
155
|
about_x_years:
|
120
|
-
one: "около {
|
121
|
-
few: "около {
|
122
|
-
many: "около {
|
123
|
-
other: "около {
|
156
|
+
one: "около %{count} года"
|
157
|
+
few: "около %{count} лет"
|
158
|
+
many: "около %{count} лет"
|
159
|
+
other: "около %{count} лет"
|
124
160
|
over_x_years:
|
125
|
-
one: "больше {
|
126
|
-
few: "больше {
|
127
|
-
many: "больше {
|
128
|
-
other: "больше {
|
161
|
+
one: "больше %{count} года"
|
162
|
+
few: "больше %{count} лет"
|
163
|
+
many: "больше %{count} лет"
|
164
|
+
other: "больше %{count} лет"
|
129
165
|
almost_x_years:
|
130
|
-
one: "почти {
|
131
|
-
few: "почти {
|
132
|
-
many: "почти {
|
133
|
-
other: "почти {
|
166
|
+
one: "почти %{count} год"
|
167
|
+
few: "почти %{count} года"
|
168
|
+
many: "почти %{count} лет"
|
169
|
+
other: "почти %{count} лет"
|
170
|
+
|
134
171
|
prompts:
|
135
172
|
year: "Год"
|
136
173
|
month: "Месяц"
|
@@ -145,12 +182,12 @@ ru:
|
|
145
182
|
template:
|
146
183
|
# Заголовок сообщения об ошибке
|
147
184
|
header:
|
148
|
-
one: "{
|
149
|
-
few: "{
|
150
|
-
many: "{
|
151
|
-
other: "{
|
185
|
+
one: "%{model}: сохранение не удалось из-за %{count} ошибки"
|
186
|
+
few: "%{model}: сохранение не удалось из-за %{count} ошибок"
|
187
|
+
many: "%{model}: сохранение не удалось из-за %{count} ошибок"
|
188
|
+
other: "%{model}: сохранение не удалось из-за %{count} ошибки"
|
152
189
|
|
153
|
-
# Первый параграф сообщения об ошибке. Можно использовать макрос {
|
190
|
+
# Первый параграф сообщения об ошибке. Можно использовать макрос %{count}
|
154
191
|
#
|
155
192
|
#
|
156
193
|
# The variable :count is also available
|
@@ -160,3 +197,16 @@ ru:
|
|
160
197
|
select:
|
161
198
|
# default value for :prompt => true in FormOptionsHelper
|
162
199
|
prompt: "Выберите: "
|
200
|
+
|
201
|
+
helpers:
|
202
|
+
select:
|
203
|
+
# default value for :prompt => true in FormOptionsHelper
|
204
|
+
prompt: "Выберите: "
|
205
|
+
|
206
|
+
|
207
|
+
# Default translation keys for submit FormHelper
|
208
|
+
submit:
|
209
|
+
create: 'Создать %{model}'
|
210
|
+
update: 'Сохранить %{model}'
|
211
|
+
submit: 'Сохранить %{model}'
|
212
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
ru:
|
2
|
+
errors:
|
3
|
+
format: "%{attribute} %{message}"
|
4
|
+
|
5
|
+
messages:
|
6
|
+
inclusion: "имеет непредусмотренное значение"
|
7
|
+
exclusion: "имеет зарезервированное значение"
|
8
|
+
invalid: "имеет неверное значение"
|
9
|
+
confirmation: "не совпадает с подтверждением"
|
10
|
+
accepted: "нужно подтвердить"
|
11
|
+
empty: "не может быть пустым"
|
12
|
+
blank: "не может быть пустым"
|
13
|
+
too_long:
|
14
|
+
one: "слишком большой длины (не может быть больше чем %{count} символ)"
|
15
|
+
few: "слишком большой длины (не может быть больше чем %{count} символа)"
|
16
|
+
many: "слишком большой длины (не может быть больше чем %{count} символов)"
|
17
|
+
other: "слишком большой длины (не может быть больше чем %{count} символа)"
|
18
|
+
too_short:
|
19
|
+
one: "недостаточной длины (не может быть меньше %{count} символа)"
|
20
|
+
few: "недостаточной длины (не может быть меньше %{count} символов)"
|
21
|
+
many: "недостаточной длины (не может быть меньше %{count} символов)"
|
22
|
+
other: "недостаточной длины (не может быть меньше %{count} символа)"
|
23
|
+
wrong_length:
|
24
|
+
one: "неверной длины (может быть длиной ровно %{count} символ)"
|
25
|
+
few: "неверной длины (может быть длиной ровно %{count} символа)"
|
26
|
+
many: "неверной длины (может быть длиной ровно %{count} символов)"
|
27
|
+
other: "неверной длины (может быть длиной ровно %{count} символа)"
|
28
|
+
taken: "уже существует"
|
29
|
+
not_a_number: "не является числом"
|
30
|
+
not_an_integer: "не является целым числом"
|
31
|
+
greater_than: "может иметь значение большее %{count}"
|
32
|
+
greater_than_or_equal_to: "может иметь значение большее или равное %{count}"
|
33
|
+
equal_to: "может иметь лишь значение, равное %{count}"
|
34
|
+
less_than: "может иметь значение меньшее чем %{count}"
|
35
|
+
less_than_or_equal_to: "может иметь значение меньшее или равное %{count}"
|
36
|
+
odd: "может иметь лишь четное значение"
|
37
|
+
even: "может иметь лишь нечетное значение"
|
38
|
+
record_invalid: "Возникли ошибки: %{errors}"
|
39
|
+
|
40
|
+
template:
|
41
|
+
# Заголовок сообщения об ошибке
|
42
|
+
header:
|
43
|
+
one: "%{model}: сохранение не удалось из-за %{count} ошибки"
|
44
|
+
few: "%{model}: сохранение не удалось из-за %{count} ошибок"
|
45
|
+
many: "%{model}: сохранение не удалось из-за %{count} ошибок"
|
46
|
+
other: "%{model}: сохранение не удалось из-за %{count} ошибки"
|
47
|
+
|
48
|
+
# Первый параграф сообщения об ошибке. Можно использовать макрос %{count}
|
49
|
+
# The variable :count is also available
|
50
|
+
body: "Проблемы возникли со следующими полями:"
|