cm-ru_propisju 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5c6ed9fd84239013e1f843a17b8d5e6659438553
4
+ data.tar.gz: 2acb17150b1b40198ef65540f8184490fb252ce1
5
+ SHA512:
6
+ metadata.gz: 034a7a27a9bc876b07fc5ee8337a7bf5b7665eee93ebfdf1cce3e335e2cfbcc1558bd9337c69d5a5d3b0ca36e28ca85900de4e48fac38948d787aa95e6e6e761
7
+ data.tar.gz: aa8aa75b1e4b500e963be6c62a015ce47a61020e194e046c4f504db97f950859c3e95b11f8f3d0b817b5293f73c666a1f4086ebd261b2d913f3b121299097842
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development do
4
+ gem "jeweler", '1.8.4' # Last one without the stupid nokogiri dependency
5
+ gem "rake"
6
+ gem "test-unit"
7
+ end
@@ -0,0 +1,61 @@
1
+ === 2.4.0
2
+
3
+ * Добавлен творительный падеж (только для русской локали) (https://github.com/julik/ru_propisju/pull/15)
4
+
5
+ === 2.3.0
6
+
7
+ * Добавлена поддержка казахстанского тенге - nodkz
8
+
9
+ === 2.2.3
10
+
11
+ * Более строгое форматирование долей (https://github.com/julik/ru_propisju/pull/12)
12
+
13
+ === 2.2.2
14
+
15
+ * Форматирование долей могло вызвать ошибку (https://github.com/julik/ru_propisju/issues/10)
16
+
17
+ === 2.2.1
18
+
19
+ * Опечатка в украинских числительных (https://github.com/julik/ru_propisju/pull/9)
20
+
21
+ === 2.2.0
22
+
23
+ * Добавлены методы rublej_extended_format, digit_rublej
24
+
25
+ === 2.1.4
26
+
27
+ * Правильная обработка нулей в суммах
28
+
29
+ === 2.1.3
30
+
31
+ * Починен порядок тысячных долей на ruby 1.8x
32
+
33
+ === 2.1.2
34
+
35
+ * Починено https://github.com/julik/ru_propisju/issues/5
36
+
37
+ === 2.1.1
38
+
39
+ * Починено https://github.com/julik/ru_propisju/issues/3
40
+
41
+ === 2.1.0
42
+
43
+ * Восстановлен старый API для choose_plural
44
+ * Добавлено исключение UnknownLocale
45
+
46
+ === 2.0.0
47
+
48
+ * Добавлена поддержка украинского языка - iz65535
49
+
50
+ === 1.2.0
51
+
52
+ * Добавлена поддержка И Еще Нескольких Валют (тм) - terraplane
53
+
54
+ === 1.1.0
55
+
56
+ * На самом деле количество копеек пишется цифрами
57
+
58
+ === 1.0.0
59
+
60
+ * Модуль вынут из RuTils
61
+
@@ -0,0 +1,52 @@
1
+ = ru_propisju
2
+
3
+ * http://github.com/julik/ru_propisju
4
+
5
+ == DESCRIPTION:
6
+
7
+ Выводит сумму прописью и суммы копеек, рублей и гривен. Помогает в выборе правильного числительного.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ Прекрасность.
12
+
13
+ == SYNOPSIS:
14
+
15
+ RuPropisju.rublej(123.78) #=> "сто двадцать три рубля 78 копеек"
16
+ RuPropisju.propisju_shtuk(212.40, 2, ["сволочь", "сволочи", "сволочей"]) #=> "двести двенадцать целых четыре десятых сволочи"
17
+ RuPropisju.rublej_extended_format(1000, :ru, fraction_formatter: '%02d', integrals_formatter: '+ %d', integrals_delimiter: ' ', always_show_fraction: true) #=> "+ 1 000 рублей 00 копеек (одна тысяча рублей 00 копеек)"
18
+
19
+ 'Продается в ' + RuPropisju.propisju_shtuk(147, 1, ["городе", "городах", "городах"], :ru_in) #=> "Продается в ста сорока семи городах"
20
+
21
+ == REQUIREMENTS:
22
+
23
+ * Прямые руки
24
+
25
+ == INSTALL:
26
+
27
+ sudo gem install ru_propisju
28
+
29
+ == LICENSE:
30
+
31
+ (The MIT License)
32
+
33
+ Copyright (c) 2011 me@julik.nl
34
+
35
+ Permission is hereby granted, free of charge, to any person obtaining
36
+ a copy of this software and associated documentation files (the
37
+ 'Software'), to deal in the Software without restriction, including
38
+ without limitation the rights to use, copy, modify, merge, publish,
39
+ distribute, sublicense, and/or sell copies of the Software, and to
40
+ permit persons to whom the Software is furnished to do so, subject to
41
+ the following conditions:
42
+
43
+ The above copyright notice and this permission notice shall be
44
+ included in all copies or substantial portions of the Software.
45
+
46
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
47
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
48
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
49
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
50
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
51
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
52
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # -*- ruby -*-
3
+ $KCODE = 'u' if RUBY_VERSION < '1.9.0'
4
+
5
+ require 'rubygems'
6
+ require 'jeweler'
7
+ require './lib/ru_propisju'
8
+
9
+ Jeweler::Tasks.new do |gem|
10
+ gem.version = RuPropisju::VERSION
11
+ gem.name = "ru_propisju"
12
+ gem.summary = "Cумма прописью"
13
+ gem.email = "me@julik.nl"
14
+ gem.homepage = "http://github.com/julik/ru_propisju"
15
+ gem.authors = ["Julik Tarkhanov"]
16
+ gem.license = 'MIT'
17
+
18
+ # Do not package invisibles
19
+ gem.files.exclude ".*"
20
+ end
21
+ Jeweler::RubygemsDotOrgTasks.new
22
+
23
+ require 'rake/testtask'
24
+ desc "Run all tests"
25
+ Rake::TestTask.new("test") do |t|
26
+ t.libs << "test"
27
+ t.pattern = 'test/**/test_*.rb'
28
+ t.verbose = true
29
+ end
30
+
31
+ task :default => [ :test ]
32
+
33
+ # vim: syntax=ruby
@@ -0,0 +1,50 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{cm-ru_propisju}
8
+ s.version = "2.4.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Julik Tarkhanov"]
12
+ s.date = %q{2015-04-13}
13
+ s.email = %q{me@julik.nl}
14
+ s.extra_rdoc_files = [
15
+ "README.rdoc"
16
+ ]
17
+ s.files = [
18
+ "Gemfile",
19
+ "History.txt",
20
+ "README.rdoc",
21
+ "Rakefile",
22
+ "lib/ru_propisju.rb",
23
+ "cm-ru_propisju.gemspec",
24
+ "test/test_ru_propisju.rb"
25
+ ]
26
+ s.homepage = %q{http://github.com/julik/ru_propisju}
27
+ s.licenses = ["MIT"]
28
+ s.require_paths = ["lib"]
29
+ s.rubygems_version = %q{1.6.2}
30
+ s.summary = %q{Cумма прописью}
31
+
32
+ if s.respond_to? :specification_version then
33
+ s.specification_version = 3
34
+
35
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
36
+ s.add_development_dependency(%q<jeweler>, ["= 1.8.4"])
37
+ s.add_development_dependency(%q<rake>, [">= 0"])
38
+ s.add_development_dependency(%q<test-unit>, [">= 0"])
39
+ else
40
+ s.add_dependency(%q<jeweler>, ["= 1.8.4"])
41
+ s.add_dependency(%q<rake>, [">= 0"])
42
+ s.add_dependency(%q<test-unit>, [">= 0"])
43
+ end
44
+ else
45
+ s.add_dependency(%q<jeweler>, ["= 1.8.4"])
46
+ s.add_dependency(%q<rake>, [">= 0"])
47
+ s.add_dependency(%q<test-unit>, [">= 0"])
48
+ end
49
+ end
50
+
@@ -0,0 +1,766 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $KCODE = 'u' if RUBY_VERSION < '1.9.0'
3
+
4
+ # Самый лучший, прекрасный, кривой и неотразимый суперпечататель суммы прописью для Ruby.
5
+ #
6
+ # RuPropisju.rublej(123) # "сто двадцать три рубля"
7
+ module RuPropisju
8
+
9
+ VERSION = '2.4.0'
10
+
11
+ # http://www.xe.com/symbols.php
12
+ # (лица, приближенные форексам и всяким там валютам и курсам)
13
+ # говорят, что код валюты российского рубля - rub
14
+ CURRENCIES = {
15
+ "rur" => :rublej,
16
+ "rub" => :rublej,
17
+ "usd" => :dollarov,
18
+ "uah" => :griven,
19
+ "eur" => :evro,
20
+ "kzt" => :tenge,
21
+ }
22
+
23
+ SUPPORTED_CURRENCIES = CURRENCIES.keys.join ','
24
+
25
+ TRANSLATIONS = {
26
+ 'ru' => {
27
+ 0 => "",
28
+ '0' => "ноль",
29
+ :thousands => ["тысяча", "тысячи", "тысяч"],
30
+ :millions => ["миллион", "миллиона", "миллионов"],
31
+ :billions => ["миллиард", "миллиарда", "миллиардов"],
32
+ 100 => "сто",
33
+ 200 => "двести",
34
+ 300 => "триста",
35
+ 400 => "четыреста",
36
+ 500 => "пятьсот",
37
+ 600 => "шестьсот",
38
+ 700 => "семьсот",
39
+ 800 => "восемьсот",
40
+ 900 => "девятьсот",
41
+
42
+ 10 => "десять",
43
+ 11 => "одиннадцать",
44
+ 12 => "двенадцать",
45
+ 13 => "тринадцать",
46
+ 14 => "четырнадцать",
47
+ 15 => "пятнадцать",
48
+ 16 => "шестнадцать",
49
+ 17 => "семнадцать",
50
+ 18 => "восемнадцать",
51
+ 19 => "девятнадцать",
52
+ 20 => "двадцать",
53
+ 30 => "тридцать",
54
+ 40 => "сорок",
55
+ 50 => "пятьдесят",
56
+ 60 => "шестьдесят",
57
+ 70 => "семьдесят",
58
+ 80 => "восемьдесят",
59
+ 90 => "девяносто",
60
+ # единицы, местами - c учетом рода
61
+ 1 => {1 => "один", 2 => 'одна', 3 => 'одно'},
62
+ 2 => {1 => "два", 2 => 'две', 3 => 'два'},
63
+ 3 => "три",
64
+ 4 => "четыре",
65
+ 5 => "пять",
66
+ 6 => "шесть",
67
+ 7 => "семь",
68
+ 8 => "восемь",
69
+ 9 => "девять",
70
+ :rub_integral => ["рубль", "рубля", "рублей"],
71
+ :rub_fraction => ['копейка', 'копейки', 'копеек'],
72
+ :uah_integral => ["гривна", "гривны", "гривен"],
73
+ :uah_fraction => ['копейка', 'копейки', 'копеек'],
74
+ :kzt_integral => ["тенге", "тенге", "тенге"],
75
+ :kzt_fraction => ['тиын', 'тиына', 'тиынов'],
76
+ :eur_integral => ["евро", "евро", "евро"],
77
+ # по опыту моей прошлой работы в банке
78
+ # центами называют дробную часть доллара
79
+ # а дробную часть евро называют евроцентом
80
+ :eur_fraction => ["цент", "цента", "центов"],
81
+ :usd_integral => ["доллар", "доллара", "долларов"],
82
+ :usd_fraction => ['цент', 'цента', 'центов'],
83
+ },
84
+ 'ru_in' => { # Предложный падеж, например в 2 городах
85
+ 0 => "",
86
+ '0' => "нуле",
87
+ :thousands => ["тысяче", "тысячах", "тысячах"],
88
+ :millions => ["миллионе", "миллионах", "миллионах"],
89
+ :billions => ["миллиарде", "миллиардах", "миллиардах"],
90
+ 100 => "ста",
91
+ 200 => "двухстах",
92
+ 300 => "трёхстах",
93
+ 400 => "четырёхстах",
94
+ 500 => "пятистах",
95
+ 600 => "шестистах",
96
+ 700 => "семистах",
97
+ 800 => "восьмистах",
98
+ 900 => "девятистах",
99
+
100
+ 10 => "десяти",
101
+ 11 => "одиннадцати",
102
+ 12 => "двенадцати",
103
+ 13 => "тринадцати",
104
+ 14 => "четырнадцати",
105
+ 15 => "пятнадцати",
106
+ 16 => "шестнадцати",
107
+ 17 => "семнадцати",
108
+ 18 => "восемнадцати",
109
+ 19 => "девятнадцати",
110
+ 20 => "двадцати",
111
+ 30 => "тридцати",
112
+ 40 => "сорока",
113
+ 50 => "пятидесяти",
114
+ 60 => "шестидесяти",
115
+ 70 => "семидесяти",
116
+ 80 => "восьмидесяти",
117
+ 90 => "девяноста",
118
+ # единицы, местами - c учетом рода
119
+ 1 => { 1 => 'одном', 2 => 'одной', 3 => 'одном' },
120
+ 2 => { 1 => 'двух', 2 => 'двух', 3 => 'двух' },
121
+ 3 => "трёх",
122
+ 4 => "четырёх",
123
+ 5 => "пяти",
124
+ 6 => "шести",
125
+ 7 => "семи",
126
+ 8 => "восьми",
127
+ 9 => "девяти",
128
+ :rub_integral => %w[рубле рублях рублях],
129
+ :rub_fraction => %w[копейке копейках копейках],
130
+ :uah_integral => %w[гривне гривнах гривнах],
131
+ :uah_fraction => %w[копейке копейках копейках],
132
+ :kzt_integral => %w[тенге тенге тенге],
133
+ :kzt_fraction => %w[тиыне тиынах тиынах],
134
+ :eur_integral => %w[евро евро евро],
135
+ # по опыту моей прошлой работы в банке
136
+ # центами называют дробную часть доллара
137
+ # а дробную часть евро называют евроцентом
138
+ :eur_fraction => %w[центе центах центах],
139
+ :usd_integral => %w[долларе долларах долларах],
140
+ :usd_fraction => %w[центе центах центах],
141
+ },
142
+ 'ru_gen' => { # Родительный падеж, например в течение одного рабочего дня, пяти ночей (нуля рабочих дней)
143
+ 0 => '',
144
+ '0' => 'нуля',
145
+ :thousands => %w[тысячи тысяч тысяч],
146
+ :millions => %w[миллиона миллионов миллионов],
147
+ :billions => %w[миллиарда миллиардов миллиардов],
148
+ 100 => 'ста',
149
+ 200 => 'двухсот',
150
+ 300 => 'трёхсот',
151
+ 400 => 'четырёхсот',
152
+ 500 => 'пятисот',
153
+ 600 => 'шестисот',
154
+ 700 => 'семисот',
155
+ 800 => 'восьмисот',
156
+ 900 => 'девятисот',
157
+
158
+ 10 => 'десяти',
159
+ 11 => 'одиннадцати',
160
+ 12 => 'двенадцати',
161
+ 13 => 'тринадцати',
162
+ 14 => 'четырнадцати',
163
+ 15 => 'пятнадцати',
164
+ 16 => 'шестнадцати',
165
+ 17 => 'семнадцати',
166
+ 18 => 'восемнадцати',
167
+ 19 => 'девятнадцати',
168
+ 20 => 'двадцати',
169
+ 30 => 'тридцати',
170
+ 40 => 'сорока',
171
+ 50 => 'пятидесяти',
172
+ 60 => 'шестидесяти',
173
+ 70 => 'семидесяти',
174
+ 80 => 'восьмидесяти',
175
+ 90 => 'девяноста',
176
+ # единицы, местами - c учетом рода
177
+ 1 => { 1 => 'одного', 2 => 'одной', 3 => 'одного' },
178
+ 2 => { 1 => 'двух', 2 => 'двух', 3 => 'двух' },
179
+ 3 => 'трёх',
180
+ 4 => 'четырёх',
181
+ 5 => 'пяти',
182
+ 6 => 'шести',
183
+ 7 => 'семи',
184
+ 8 => 'восьми',
185
+ 9 => 'девяти',
186
+ :rub_integral => %w[рубля рублей рублей],
187
+ :rub_fraction => %w[копейки копеек копеек],
188
+ :uah_integral => %w[гривны гривен гривен],
189
+ :uah_fraction => %w[копейки копеек копеек],
190
+ :kzt_integral => %w[тенге тенге тенге],
191
+ :kzt_fraction => %w[тиына тиынов тиынов],
192
+ :eur_integral => %w[евро евро евро],
193
+ # TODO: решить как же всё-таки звать дробную часть евро: "цент" или "евроцент"
194
+ :eur_fraction => %w[цента центов центов],
195
+ :usd_integral => %w[доллара долларов долларов],
196
+ :usd_fraction => %w[цента центов центов],
197
+ },
198
+ 'ru_from' => {
199
+ 0 => "",
200
+ '0' => "нулём",
201
+ :thousands => ["тысячю", "тысячами", "тысячами"],
202
+ :millions => ["миллионом", "миллионами", "миллионами"],
203
+ :billions => ["миллиардом", "миллиардами", "миллиардами"],
204
+ 100 => "ста",
205
+ 200 => "двумястами",
206
+ 300 => "тремястами",
207
+ 400 => "четырьмястами",
208
+ 500 => "пятьюстами",
209
+ 600 => "шестьюстами",
210
+ 700 => "семьюстами",
211
+ 800 => "восьмьюстами",
212
+ 900 => "девятьюстами",
213
+
214
+ 10 => "десятью",
215
+ 11 => "одиннадцатью",
216
+ 12 => "двенадцатью",
217
+ 13 => "тринадцатью",
218
+ 14 => "четырнадцатью",
219
+ 15 => "пятнадцатью",
220
+ 16 => "шестнадцатью",
221
+ 17 => "семнадцатью",
222
+ 18 => "восемнадцатью",
223
+ 19 => "девятнадцатью",
224
+ 20 => "двадцатью",
225
+ 30 => "тридцатью",
226
+ 40 => "сорока",
227
+ 50 => "пятьюдесятью",
228
+ 60 => "шестьюдесятью",
229
+ 70 => "семьюдесятью",
230
+ 80 => "восьмьюдесятью",
231
+ 90 => "девяноста",
232
+ # единицы, местами - c учетом рода
233
+ 1 => {1 => "одним", 2 => 'одной', 3 => 'одним'},
234
+ 2 => {1 => "двумя", 2 => 'двумя', 3 => 'двумя'},
235
+ 3 => "тремя",
236
+ 4 => "четырьмя",
237
+ 5 => "пятью",
238
+ 6 => "шестью",
239
+ 7 => "семью",
240
+ 8 => "восьмью",
241
+ 9 => "девятью",
242
+ :rub_integral => ["рублём", "рублями", "рублями"],
243
+ :rub_fraction => ['копейкой', 'копейками', 'копейками'],
244
+ :uah_integral => ["гривной", "гривнами", "гривнами"],
245
+ :uah_fraction => ['копейкой', 'копейками', 'копейками'],
246
+ :kzt_integral => ["тенге", "тенге", "тенге"],
247
+ :kzt_fraction => ['тиыной', 'тиынами', 'тиынами'],
248
+ :eur_integral => ["евро", "евро", "евро"],
249
+ # по опыту моей прошлой работы в банке
250
+ # центами называют дробную часть доллара
251
+ # а дробную часть евро называют евроцентом
252
+ :eur_fraction => ["центом", "центами", "центами"],
253
+ :usd_integral => ["долларом", "долларами", "долларами"],
254
+ :usd_fraction => ['центом', 'центами', 'центами'],
255
+ },
256
+ 'ua' => {
257
+ 0 => "",
258
+ '0' => "нуль",
259
+ :thousands => ["тисяча", "тисячі", "тисяч"],
260
+ :millions => ["мільйон", "мільйона", "мільйонів"],
261
+ :billions => ["мільярд", "мільярда", "мільярдів"],
262
+ 100 => "сто",
263
+ 200 => "двісті",
264
+ 300 => "триста",
265
+ 400 => "чотириста",
266
+ 500 => "п'ятьсот",
267
+ 600 => "шістсот",
268
+ 700 => "сімсот",
269
+ 800 => "вісімсот",
270
+ 900 => "дев'ятсот",
271
+
272
+ 10 => "десять",
273
+ 11 => "одинадцять",
274
+ 12 => "дванадцять",
275
+ 13 => "тринадцять",
276
+ 14 => "чотирнадцять",
277
+ 15 => "п'ятнадцять",
278
+ 16 => "шістнадцять",
279
+ 17 => "сімнадцять",
280
+ 18 => "вісімнадцять",
281
+ 19 => "дев'ятнадцять",
282
+ 20 => "двадцять",
283
+ 30 => "тридцять",
284
+ 40 => "сорок",
285
+ 50 => "п'ятьдесят",
286
+ 60 => "шістдесят",
287
+ 70 => "сімдесят",
288
+ 80 => "вісімдесят",
289
+ 90 => "дев'яносто",
290
+ # единицы, местами - c учетом рода
291
+ 1 => {1 => "один", 2 => 'одна', 3 => 'одне'},
292
+ 2 => {1 => "два", 2 => 'дві', 3 => 'два'},
293
+ 3 => "три",
294
+ 4 => "чотири",
295
+ 5 => "п'ять",
296
+ 6 => "шість",
297
+ 7 => "сім",
298
+ 8 => "вісім",
299
+ 9 => "дев'ять",
300
+ :rub_integral => ["рубль", "рубля", "рублів"],
301
+ :rub_fraction => ['копійка', 'копійки', 'копійок'],
302
+ :uah_integral => ["гривня", "гривні", "гривень"],
303
+ :uah_fraction => ["копійка", "копійки", "копійок"],
304
+ :kzt_integral => ["тенге", "тенге", "тенге"],
305
+ :kzt_fraction => ['тиын', 'тиына', 'тиынов'],
306
+ :eur_integral => ["євро", "євро", "євро"],
307
+ :eur_fraction => ["євроцент", "євроцента", "євроцентів"],
308
+ :usd_integral => ["долар", "долара", "доларів"],
309
+ :usd_fraction => ['цент', 'цента', 'центів'],
310
+ }
311
+ }
312
+ # Переименовал предложный падеж из _in в _pre (prepositional)
313
+ # Оставил 'ru_in' для обратной совместимости
314
+ TRANSLATIONS['ru_pre'] = TRANSLATIONS['ru_in']
315
+
316
+ MONEY_GENDERS = {
317
+ :rub => 1,
318
+ :usd => 1,
319
+ :uah => 2,
320
+ :eur => 1,
321
+ :kzt => 1,
322
+ }
323
+
324
+
325
+ # Кидается при запросе неизвестной валюты
326
+ class UnknownCurrency < ArgumentError
327
+ end
328
+
329
+ # Кидается при запросе неизвестного языка
330
+ class UnknownLocale < ArgumentError
331
+ end
332
+
333
+ # Выбирает нужный падеж существительного в зависимости от числа
334
+ #
335
+ # choose_plural(3, "штука", "штуки", "штук") #=> "штуки"
336
+ def choose_plural(amount, *variants)
337
+ variants = variants.flatten
338
+
339
+ mod_ten = amount % 10
340
+ mod_hundred = amount % 100
341
+ variant = if (mod_ten == 1 && mod_hundred != 11)
342
+ 1
343
+ else
344
+ if mod_ten >= 2 && mod_ten <= 4 && (mod_hundred <10 || mod_hundred % 100>=20)
345
+ 2
346
+ else
347
+ 3
348
+ end
349
+ end
350
+ variants[variant-1]
351
+ end
352
+
353
+ # Выводит сумму прописью в зависимости от выбранной валюты.
354
+ # Поддерживаемые валюты: rur, usd, uah, eur
355
+ #
356
+ # amount_in_words(345.2, 'rur') #=> "триста сорок пять рублей 20 копеек"
357
+ def amount_in_words(amount, currency, locale = :ru, options = {})
358
+ currency = currency.to_s.downcase
359
+ unless CURRENCIES.has_key? currency
360
+ raise UnknownCurrency, "Unsupported currency #{currency}, the following are supported: #{SUPPORTED_CURRENCIES}"
361
+ end
362
+ method(CURRENCIES[currency]).call(amount, locale, options)
363
+ end
364
+
365
+ # Выводит целое или дробное число как сумму в рублях прописью
366
+ #
367
+ # rublej(345.2) #=> "триста сорок пять рублей 20 копеек"
368
+ #
369
+ def rublej(amount, locale = :ru, options = {})
370
+ integrals_key = :rub_integral
371
+ fractions_key = :rub_fraction
372
+ money_gender = MONEY_GENDERS[:rub]
373
+
374
+ money(amount, locale, integrals_key, fractions_key, money_gender, true, false, options)
375
+ end
376
+
377
+ # Выводит целое или дробное число как сумму в расширенном формате
378
+ #
379
+ # rublej_extended_format(345.2) #=> "345 рублей 20 копеек (триста сорок пять рублей 20 копеек)"
380
+ #
381
+ def rublej_extended_format(amount, locale = :ru, options = {})
382
+ "#{digit_rublej(amount, locale, options)} (#{rublej(amount, locale, options)})"
383
+ end
384
+
385
+ # Выводит целое или дробное число как сумму в рублях и копейках не прописью
386
+ #
387
+ # digit_rublej(345.2) #=> "345 рублей 20 копеек"
388
+ #
389
+
390
+ def digit_rublej(amount, locale = :ru, options = {})
391
+ integrals_key = :rub_integral
392
+ fractions_key = :rub_fraction
393
+ money_gender = MONEY_GENDERS[:rub]
394
+
395
+ money(amount, locale, integrals_key, fractions_key, money_gender, true, true, options)
396
+ end
397
+ # Выбирает корректный вариант числительного в зависимости от рода и числа и оформляет сумму прописью
398
+ #
399
+ # propisju(243, 1) => "двести сорок три"
400
+ # propisju(221, 2) => "двести двадцать одна"
401
+ def propisju(amount, gender, locale = :ru)
402
+ if amount.is_a?(Integer) || amount.is_a?(Bignum)
403
+ propisju_int(amount, gender, [], locale)
404
+ else # также сработает для Decimal, дробные десятичные числительные в долях поэтому женского рода
405
+ propisju_float(amount, locale)
406
+ end
407
+ end
408
+
409
+ # Выводит целое или дробное число как сумму в гривнах прописью
410
+ #
411
+ # griven(32) #=> "тридцать две гривны"
412
+ def griven(amount, locale = :ru, options = {})
413
+ integrals_key = :uah_integral
414
+ fractions_key = :uah_fraction
415
+ money_gender = MONEY_GENDERS[:uah]
416
+
417
+ money(amount, locale, integrals_key, fractions_key, money_gender, false, false, options)
418
+ end
419
+
420
+ # Выводит целое или дробное число как сумму в долларах прописью
421
+ #
422
+ # dollarov(32) #=> "тридцать два доллара"
423
+ def dollarov(amount, locale = :ru, options = {})
424
+ integrals_key = :usd_integral
425
+ fractions_key = :usd_fraction
426
+ money_gender = MONEY_GENDERS[:usd]
427
+
428
+ money(amount, locale, integrals_key, fractions_key, money_gender, false, false, options)
429
+ end
430
+
431
+ # Выводит целое или дробное число как сумму в евро прописью
432
+ #
433
+ # evro(32) #=> "тридцать два евро"
434
+ def evro(amount, locale = :ru, options = {})
435
+ integrals_key = :eur_integral
436
+ fractions_key = :eur_fraction
437
+ money_gender = MONEY_GENDERS[:eur]
438
+
439
+ money(amount, locale, integrals_key, fractions_key, money_gender, false, false, options)
440
+ end
441
+
442
+ # Выводит целое или дробное число как сумму в тенге прописью
443
+ #
444
+ # tenge(32) #=> "тридцать два тенге"
445
+ def tenge(amount, locale = :ru, options = {})
446
+ integrals_key = :kzt_integral
447
+ fractions_key = :kzt_fraction
448
+ money_gender = MONEY_GENDERS[:kzt]
449
+
450
+ money(amount, locale, integrals_key, fractions_key, money_gender, false, false, options)
451
+ end
452
+
453
+ # Выводит сумму прописью в рублях по количеству копеек
454
+ #
455
+ # kopeek(343) #=> "три рубля 43 копейки"
456
+ def kopeek(amount, locale = :ru, options = {})
457
+ rublej(amount / 100.0, locale, options)
458
+ end
459
+
460
+ # Выводит сумму данного существительного прописью и выбирает правильное число и падеж
461
+ #
462
+ # RuPropisju.propisju_shtuk(21, 3, "колесо", "колеса", "колес") #=> "двадцать одно колесо"
463
+ # RuPropisju.propisju_shtuk(21, 1, "мужик", "мужика", "мужиков") #=> "двадцать один мужик"
464
+ def propisju_shtuk(items, gender, forms, locale = :ru)
465
+ elements = if (items == items.to_i)
466
+ [propisju(items, gender, locale), choose_plural(items, forms)]
467
+ else
468
+ [propisju(items, gender, locale), forms[1]]
469
+ end
470
+
471
+ elements.join(" ")
472
+ end
473
+
474
+ def money(amount, locale, integrals_key, fractions_key, money_gender, fraction_as_number = false, integrals_as_number = false, options = {})
475
+
476
+ options[:integrals_formatter] ||= '%d'
477
+ options[:fraction_formatter] ||= '%d'
478
+ options[:integrals_delimiter] ||= ''
479
+ options[:always_show_fraction] ||= false
480
+
481
+ locale_data = pick_locale(TRANSLATIONS, locale)
482
+ integrals = locale_data[integrals_key]
483
+ fractions = locale_data[fractions_key]
484
+ return zero(locale_data, integrals, fractions, fraction_as_number, integrals_as_number, options) if amount.zero?
485
+ parts = []
486
+
487
+ unless amount.to_i == 0
488
+ if integrals_as_number
489
+ parts << format_integral(amount.to_i, options) << choose_plural(amount.to_i, integrals)
490
+ else
491
+ parts << propisju_int(amount.to_i, money_gender, integrals, locale)
492
+ end
493
+ end
494
+
495
+ if amount.kind_of?(Float)
496
+ remainder = (amount.divmod(1)[1]*100).round
497
+ if remainder == 100
498
+ parts = [propisju_int(amount.to_i + 1, money_gender, integrals, locale)]
499
+ parts << format(options[:fraction_formatter], 0) << choose_plural(0, fractions) if options[:always_show_fraction]
500
+ else
501
+ if fraction_as_number
502
+ kop = remainder.to_i
503
+ if (!kop.zero? || options[:always_show_fraction])
504
+ parts << format(options[:fraction_formatter], kop) << choose_plural(kop, fractions)
505
+ end
506
+ else
507
+ parts << propisju_int(remainder.to_i, money_gender, fractions, locale)
508
+ end
509
+ end
510
+ else
511
+ parts << format(options[:fraction_formatter], 0) << choose_plural(0, fractions) if options[:always_show_fraction]
512
+ end
513
+
514
+ parts.join(' ')
515
+ end
516
+
517
+ private
518
+
519
+ def zero(locale_data, integrals, fractions, fraction_as_number, integrals_as_number, options)
520
+ integ = integrals_as_number ? format(options[:integrals_formatter], 0) : locale_data['0']
521
+ frac = fraction_as_number ? format(options[:fraction_formatter], 0) : locale_data['0']
522
+ parts = [integ , integrals[-1], frac, fractions[-1]]
523
+ parts.join(' ')
524
+ end
525
+
526
+ # Cоставляет число прописью для чисел до тысячи
527
+
528
+ def compose_ordinal(remaining_amount_or_nil, gender, item_forms = [], locale = :ru)
529
+
530
+ remaining_amount = remaining_amount_or_nil.to_i
531
+
532
+ locale = locale.to_s
533
+
534
+ # Ноль чего-то
535
+ # return "ноль %s" % item_forms[3] if remaining_amount_or_nil.zero?
536
+
537
+ rest, rest1, chosen_ordinal, ones, tens, hundreds = [nil]*6
538
+
539
+ rest = remaining_amount % 1000
540
+ remaining_amount = remaining_amount / 1000
541
+ if rest.zero?
542
+ # последние три знака нулевые
543
+ return item_forms[2]
544
+ end
545
+
546
+ locale_root = pick_locale(TRANSLATIONS, locale)
547
+
548
+ # начинаем подсчет с Rest
549
+ # сотни
550
+ hundreds = locale_root[(rest / 100).to_i * 100]
551
+
552
+ # десятки
553
+ rest = rest % 100
554
+ rest1 = rest / 10
555
+
556
+ # единички
557
+ ones = ""
558
+ tens = locale_root[rest1 == 1 ? rest : rest1 * 10]
559
+
560
+ # индекс выбранной формы
561
+ chosen_ordinal = 2
562
+ if rest1 < 1 || rest1 > 1 # единицы
563
+ value = locale_root[rest % 10]
564
+ # если попался хэш, делаем выбор согласно рода
565
+ value = value[gender] if value.kind_of? Hash
566
+ ones = value
567
+ case rest % 10
568
+ when 1 then chosen_ordinal = 0 # индекс формы меняется
569
+ when 2..4 then chosen_ordinal = 1 # индекс формы меняется
570
+ end
571
+ end
572
+ plural = [
573
+ hundreds,
574
+ tens,
575
+ ones,
576
+ item_forms[chosen_ordinal],
577
+ ].compact.reject(&:empty?).join(' ').strip
578
+
579
+ return plural
580
+ end
581
+
582
+ DECIMALS = {
583
+ 'ru' =>{
584
+ :source_words => [
585
+ 'целая',
586
+ 'десятая',
587
+ 'сотая',
588
+ 'тысячная',
589
+ 'десятитысячная',
590
+ 'стотысячная',
591
+ 'миллионная',
592
+ 'десятимиллионная',
593
+ 'стомиллионная',
594
+ 'миллиардная',
595
+ 'десятимиллиардная',
596
+ 'стомиллиардная',
597
+ 'триллионная'
598
+ ],
599
+ :prefix => ["ая", 'ых'],
600
+ },
601
+ 'ru_in' =>{
602
+ :source_words => [
603
+ 'целой',
604
+ 'десятой',
605
+ 'сотой',
606
+ 'тысячной',
607
+ 'десятитысячной',
608
+ 'стотысячной',
609
+ 'миллионной',
610
+ 'десятимиллионной',
611
+ 'стомиллионной',
612
+ 'миллиардной',
613
+ 'десятимиллиардной',
614
+ 'стомиллиардной',
615
+ 'триллионной'
616
+ ],
617
+ :prefix => ["ой", 'ых'],
618
+ },
619
+ 'ru_from' =>{
620
+ :source_words => [
621
+ 'целой',
622
+ 'десятой',
623
+ 'сотой',
624
+ 'тысячной',
625
+ 'десятитысячной',
626
+ 'стотысячной',
627
+ 'миллионной',
628
+ 'десятимиллионной',
629
+ 'стомиллионной',
630
+ 'миллиардной',
631
+ 'десятимиллиардной',
632
+ 'стомиллиардной',
633
+ 'триллионной'
634
+ ],
635
+ :prefix => ["ой", 'ыми'],
636
+ },
637
+ 'ua' => {
638
+ :source_words => [
639
+ 'ціла',
640
+ 'десята',
641
+ 'сота',
642
+ 'тисячна',
643
+ 'десятитисячна',
644
+ 'стотисячна',
645
+ 'мільйонна',
646
+ 'десятимільйонна',
647
+ 'стомільйонна',
648
+ 'мільярдна',
649
+ 'десятимільярдна',
650
+ 'стомільярдна',
651
+ 'трильонна'
652
+ ],
653
+ :prefix => ["а", 'их'],
654
+ },
655
+ }
656
+ # Добавляем новый префикс для предложного падежа и новые значения для родительного (совпадающие с предложным)
657
+ DECIMALS['ru_pre'] = DECIMALS['ru_in']
658
+ DECIMALS['ru_gen'] = DECIMALS['ru_in']
659
+
660
+ # Выдает сумму прописью с учетом дробной доли. Дробная доля округляется до миллионной, или (если
661
+ # дробная доля оканчивается на нули) до ближайшей доли или точки ( 500 тысячных округляется до 5 десятых, 30.0000 до 30).
662
+ def propisju_float(num, locale = :ru)
663
+ locale_root = pick_locale(DECIMALS, locale)
664
+ source_expression = locale_root[:prefix][0]
665
+ target_prefix = locale_root[:prefix][1]
666
+ words = locale_root[:source_words].map do |e|
667
+ [
668
+ e,
669
+ e.gsub(/#{source_expression}$/, target_prefix),
670
+ e.gsub(/#{source_expression}$/, target_prefix),
671
+ ]
672
+ end.freeze
673
+
674
+ # Укорачиваем до триллионной доли
675
+ formatted = num.to_s[/^\d+(\.\d{0,#{words.length - 1}})?/].gsub(/0+$/, '')
676
+ wholes, decimals = formatted.split(".")
677
+
678
+ return propisju_int(wholes.to_i, 1, [], locale) if decimals.to_i.zero?
679
+
680
+ whole_st = propisju_shtuk(wholes.to_i, 2, words[0], locale)
681
+
682
+ rem_st = propisju_shtuk(decimals.to_i, 2, words[decimals.length], locale)
683
+ [whole_st, rem_st].compact.join(" ")
684
+ end
685
+
686
+ # Выполняет преобразование числа из цифрого вида в символьное
687
+ #
688
+ # amount - числительное
689
+ # gender = 1 - мужской, = 2 - женский, = 3 - средний
690
+ # one_item - именительный падеж единственного числа (= 1)
691
+ # two_items - родительный падеж единственного числа (= 2-4)
692
+ # five_items - родительный падеж множественного числа ( = 5-10)
693
+ #
694
+ # Примерно так:
695
+ # propisju(42, 1, ["сволочь", "сволочи", "сволочей"]) # => "сорок две сволочи"
696
+ def propisju_int(amount, gender = 1, item_forms = [], locale = :ru)
697
+
698
+ locale_root = pick_locale(TRANSLATIONS, locale)
699
+
700
+ # zero!
701
+ if amount.zero?
702
+ return [locale_root['0'], item_forms[-1]].compact.join(' ')
703
+ end
704
+
705
+ fractions = [
706
+ [:trillions, 1_000_000_000_000],
707
+ [:billions, 1_000_000_000],
708
+ [:millions, 1_000_000],
709
+ [:thousands, 1_000],
710
+ ]
711
+
712
+ parts = fractions.map do | name, multiplier |
713
+ [name, fraction = (amount / multiplier) % 1000]
714
+ end
715
+
716
+ # Единицы обрабатываем отдельно
717
+ ones = amount % 1000
718
+
719
+ # Составляем простые тысячные доли
720
+ parts_in_writing = parts.reject do | part |
721
+ part[1].zero?
722
+ end.map do | name, fraction |
723
+ thousandth_gender = (name == :thousands) ? 2 : 1
724
+ compose_ordinal(fraction, thousandth_gender, locale_root[name], locale)
725
+ end
726
+
727
+ # И только единицы обрабатываем с переданными параметрами
728
+ parts_in_writing.push(compose_ordinal(ones, gender, item_forms, locale))
729
+
730
+ parts_in_writing.compact.join(' ')
731
+ end
732
+
733
+ def format_integral(number, options)
734
+ formatted_number = format(options[:integrals_formatter], number)
735
+ delimited_number(formatted_number, options[:integrals_delimiter])
736
+ end
737
+
738
+ def delimited_number(number, delimiter)
739
+ return number.to_s if delimiter == ''
740
+
741
+ number.to_s.gsub!(/(\d)(?=(\d\d\d)+(?!\d))/) do |digit_to_delimit|
742
+ "#{digit_to_delimit}#{delimiter}"
743
+ end || number.to_s
744
+ end
745
+
746
+ def pick_locale(from_hash, locale)
747
+ return from_hash[locale.to_s] if from_hash.has_key?(locale.to_s)
748
+ raise UnknownLocale, "Unknown locale #{locale.inspect}"
749
+ end
750
+
751
+ alias_method :rublja, :rublej
752
+ alias_method :rubl, :rublej
753
+
754
+ alias_method :kopeika, :kopeek
755
+ alias_method :kopeiki, :kopeek
756
+
757
+ alias_method :grivna, :griven
758
+ alias_method :grivny, :griven
759
+
760
+ alias_method :dollar, :dollarov
761
+ alias_method :dollary, :dollarov
762
+
763
+ public_instance_methods(true).map{|m| module_function(m) }
764
+
765
+ module_function :zero, :propisju_int, :propisju_float, :compose_ordinal, :pick_locale, :format_integral, :delimited_number
766
+ end