rotuka-rutils 0.2.4

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,27 @@
1
+ if defined?(Object::RedCloth) && !RedCloth.instance_methods.include?(:htmlesc_without_rutils)
2
+ # RuTils выполняет перегрузку Textile Glyphs в RedCloth, перенося форматирование спецсимволов на Gilenson.
3
+ class RedCloth < String #:nodoc:
4
+
5
+ # Этот метод в RedCloth при наличии Гиленсона надо отключать
6
+ alias_method :htmlesc_without_rutils, :htmlesc
7
+ def htmlesc(text, mode=0) #:nodoc:
8
+ RuTils::overrides_enabled? ? text : htmlesc_without_rutils(text, mode)
9
+ end
10
+
11
+ # А этот метод обрабатывает Textile Glyphs - ту самую типографицу.
12
+ # Вместо того чтобы влезать в чужие таблицы мы просто заменим Textile Glyphs на Gilenson - и все будут рады.
13
+ alias_method :pgl_without_rutils, :pgl
14
+ def pgl(text) #:nodoc:
15
+ if RuTils::overrides_enabled?
16
+ # Suspend the spaces in the start and end of the block because Gilenson chews them off, and RedCloth feeds them to us in packs
17
+ # that appear between tag starts/stops. We mess up the formatting but preserve the spacing.
18
+ spaces = Array.new(2,'')
19
+ text.gsub!(/\A([\s]+)/) { spaces[0] = $1; '' }
20
+ text.gsub!(/(\s+)\Z/) { spaces[1] = $1; '' }
21
+ text.replace(spaces[0].to_s + RuTils::Gilenson::Formatter.new(text).to_html + spaces[1].to_s)
22
+ else
23
+ pgl_without_rutils(text)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,236 @@
1
+ module RuTils
2
+ module Pluralization #:nodoc:
3
+ # Выбирает нужный падеж существительного в зависимости от числа
4
+ def self.choose_plural(amount, *variants)
5
+ variant = (amount%10==1 && amount%100!=11 ? 1 : amount%10>=2 && amount%10<=4 && (amount%100<10 || amount%100>=20) ? 2 : 3)
6
+ variants[variant-1]
7
+ end
8
+
9
+ def self.rublej(amount)
10
+ pts = []
11
+
12
+ pts << RuTils::Pluralization::sum_string(amount.to_i, 1, "рубль", "рубля", "рублей") unless amount.to_i == 0
13
+ if amount.kind_of?(Float)
14
+ remainder = (amount.divmod(1)[1]*100).round
15
+ if (remainder == 100)
16
+ pts = [RuTils::Pluralization::sum_string(amount.to_i+1, 1, 'рубль', 'рубля', 'рублей')]
17
+ else
18
+ pts << RuTils::Pluralization::sum_string(remainder.to_i, 2, 'копейка', 'копейки', 'копеек')
19
+ end
20
+ end
21
+
22
+ pts.join(' ')
23
+ end
24
+
25
+ # Выполняет преобразование числа из цифрого вида в символьное
26
+ # amount - числительное
27
+ # gender = 1 - мужской, = 2 - женский, = 3 - средний
28
+ # one_item - именительный падеж единственного числа (= 1)
29
+ # two_items - родительный падеж единственного числа (= 2-4)
30
+ # five_items - родительный падеж множественного числа ( = 5-10)
31
+ def self.sum_string(amount, gender, one_item='', two_items='', five_items='')
32
+ into = ''
33
+ tmp_val ||= 0
34
+
35
+ return "ноль " + five_items if amount == 0
36
+
37
+ tmp_val = amount
38
+
39
+ # единицы
40
+ into, tmp_val = sum_string_fn(into, tmp_val, gender, one_item, two_items, five_items)
41
+
42
+ return into if tmp_val == 0
43
+
44
+ # тысячи
45
+ into, tmp_val = sum_string_fn(into, tmp_val, 2, "тысяча", "тысячи", "тысяч")
46
+
47
+ return into if tmp_val == 0
48
+
49
+ # миллионы
50
+ into, tmp_val = sum_string_fn(into, tmp_val, 1, "миллион", "миллиона", "миллионов")
51
+
52
+ return into if tmp_val == 0
53
+
54
+ # миллиардов
55
+ into, tmp_val = sum_string_fn(into, tmp_val, 1, "миллиард", "миллиарда", "миллиардов")
56
+ return into
57
+ end
58
+
59
+ private
60
+ def self.sum_string_fn(into, tmp_val, gender, one_item='', two_items='', five_items='')
61
+ rest, rest1, end_word, ones, tens, hundreds = [nil]*6
62
+ #
63
+ rest = tmp_val % 1000
64
+ tmp_val = tmp_val / 1000
65
+ if rest == 0
66
+ # последние три знака нулевые
67
+ into = five_items + " " if into == ""
68
+ return [into, tmp_val]
69
+ end
70
+ #
71
+ # начинаем подсчет с Rest
72
+ end_word = five_items
73
+ # сотни
74
+ hundreds = case rest / 100
75
+ when 0 then ""
76
+ when 1 then "сто "
77
+ when 2 then "двести "
78
+ when 3 then "триста "
79
+ when 4 then "четыреста "
80
+ when 5 then "пятьсот "
81
+ when 6 then "шестьсот "
82
+ when 7 then "семьсот "
83
+ when 8 then "восемьсот "
84
+ when 9 then "девятьсот "
85
+ end
86
+
87
+ # десятки
88
+ rest = rest % 100
89
+ rest1 = rest / 10
90
+ ones = ""
91
+ case rest1
92
+ when 0 then tens = ""
93
+ when 1 # особый случай
94
+ tens = case rest
95
+ when 10 then "десять "
96
+ when 11 then "одиннадцать "
97
+ when 12 then "двенадцать "
98
+ when 13 then "тринадцать "
99
+ when 14 then "четырнадцать "
100
+ when 15 then "пятнадцать "
101
+ when 16 then "шестнадцать "
102
+ when 17 then "семнадцать "
103
+ when 18 then "восемнадцать "
104
+ when 19 then "девятнадцать "
105
+ end
106
+ when 2: tens = "двадцать "
107
+ when 3: tens = "тридцать "
108
+ when 4: tens = "сорок "
109
+ when 5: tens = "пятьдесят "
110
+ when 6: tens = "шестьдесят "
111
+ when 7: tens = "семьдесят "
112
+ when 8: tens = "восемьдесят "
113
+ when 9: tens = "девяносто "
114
+ end
115
+ #
116
+ if rest1 < 1 or rest1 > 1 # единицы
117
+ case rest % 10
118
+ when 1
119
+ ones = case gender
120
+ when 1 then "один "
121
+ when 2 then "одна "
122
+ when 3 then "одно "
123
+ end
124
+ end_word = one_item
125
+ when 2
126
+ if gender == 2
127
+ ones = "две "
128
+ else
129
+ ones = "два "
130
+ end
131
+ end_word = two_items
132
+ when 3
133
+ ones = "три " if end_word = two_items
134
+ when 4
135
+ ones = "четыре " if end_word = two_items
136
+ when 5
137
+ ones = "пять "
138
+ when 6
139
+ ones = "шесть "
140
+ when 7
141
+ ones = "семь "
142
+ when 8
143
+ ones = "восемь "
144
+ when 9
145
+ ones = "девять "
146
+ end
147
+ end
148
+
149
+ # сборка строки
150
+ st = ''
151
+ return [(st << hundreds.to_s << tens.to_s << ones.to_s << end_word.to_s << " " << into.to_s).strip, tmp_val]
152
+ end
153
+
154
+ # Реализует вывод прописью любого объекта, реализующего Float
155
+ module FloatFormatting
156
+
157
+ # Выдает сумму прописью с учетом дробной доли. Дробная доля округляется до миллионной, или (если
158
+ # дробная доля оканчивается на нули) до ближайшей доли ( 500 тысячных округляется до 5 десятых).
159
+ # Дополнительный аргумент - род существительного (1 - мужской, 2- женский, 3-средний)
160
+ def propisju(gender = 2)
161
+ raise "Это не число!" if self.nan?
162
+
163
+ st = RuTils::Pluralization::sum_string(self.to_i, gender, "целая", "целых", "целых")
164
+
165
+ remainder = self.to_s.match(/\.(\d+)/)[1]
166
+
167
+ signs = remainder.to_s.size- 1
168
+
169
+ it = [["десятая", "десятых"]]
170
+ it << ["сотая", "сотых"]
171
+ it << ["тысячная", "тысячных"]
172
+ it << ["десятитысячная", "десятитысячных"]
173
+ it << ["стотысячная", "стотысячных"]
174
+ it << ["миллионная", "милллионных"]
175
+ it << ["десятимиллионная", "десятимилллионных", "десятимиллионных"]
176
+ it << ["стомиллионная", "стомилллионных", "стомиллионных"]
177
+ it << ["миллиардная", "миллиардных", "миллиардных"]
178
+ it << ["десятимиллиардная", "десятимиллиардных", "десятимиллиардных"]
179
+ it << ["стомиллиардная", "стомиллиардных", "стомиллиардных"]
180
+ it << ["триллионная", "триллионных", "триллионных"]
181
+
182
+ while it[signs].nil?
183
+ remainder = (remainder/10).round
184
+ signs = remainder.to_s.size- 1
185
+ end
186
+
187
+ suf1, suf2, suf3 = it[signs][0], it[signs][1], it[signs][2]
188
+ st + " " + RuTils::Pluralization::sum_string(remainder.to_i, 2, suf1, suf2, suf2)
189
+ end
190
+
191
+ def propisju_items(gender=1, *forms)
192
+ if self == self.to_i
193
+ return self.to_i.propisju_items(gender, *forms)
194
+ else
195
+ self.propisju(gender) + " " + forms[1]
196
+ end
197
+ end
198
+
199
+ end
200
+
201
+ # Реализует вывод прописью любого объекта, реализующего Numeric
202
+ module NumericFormatting
203
+ # Выбирает корректный вариант числительного в зависимости от рода и числа и оформляет сумму прописью
204
+ # 234.propisju => "двести сорок три"
205
+ # 221.propisju(2) => "двести двадцать одна"
206
+ def propisju(gender = 1)
207
+ RuTils::Pluralization::sum_string(self, gender, "")
208
+ end
209
+
210
+ def propisju_items(gender=1, *forms)
211
+ self.propisju(gender) + " " + RuTils::Pluralization::choose_plural(self.to_i, *forms)
212
+ end
213
+
214
+ # Выбирает корректный вариант числительного в зависимости от рода и числа. Например:
215
+ # * 4.items("колесо", "колеса", "колес") => "колеса"
216
+ def items(one_item, two_items, five_items)
217
+ RuTils::Pluralization::choose_plural(self, one_item, two_items, five_items)
218
+ end
219
+
220
+ # Выводит сумму в рублях прописью. Например:
221
+ # * (15.4).rublej => "пятнадцать рублей сорок копеек"
222
+ def rublej
223
+ RuTils::Pluralization::rublej(self)
224
+ end
225
+ end
226
+ end
227
+ end
228
+
229
+ class Object::Numeric
230
+ include RuTils::Pluralization::NumericFormatting
231
+ end
232
+
233
+
234
+ class Object::Float
235
+ include RuTils::Pluralization::FloatFormatting
236
+ end
@@ -0,0 +1,32 @@
1
+ $KCODE = 'u'
2
+
3
+ # Главный контейнер модуля
4
+ module RuTils
5
+ # Папка, куда установлен модуль RuTils. Нужно чтобы автоматически копировать RuTils в другие приложения.
6
+ INSTALLATION_DIRECTORY = File.expand_path(File.dirname(__FILE__) + '/../') #:nodoc:
7
+ MAJOR = 0
8
+ MINOR = 2
9
+ TINY = 3
10
+
11
+ # Версия RuTils
12
+ VERSION = [MAJOR, MINOR ,TINY].join('.') #:nodoc:
13
+
14
+ # Стандартный маркер для подстановок - invalid UTF sequence
15
+ SUBSTITUTION_MARKER = "\xF0\xF0\xF0\xF0" #:nodoc:
16
+
17
+ def self.load_component(name) #:nodoc:
18
+ require File.join(RuTils::INSTALLATION_DIRECTORY, "lib", name.to_s, name.to_s)
19
+ end
20
+
21
+ def self.reload_component(name) #:nodoc:
22
+ load File.join(RuTils::INSTALLATION_DIRECTORY, "lib", name.to_s, "#{name}.rb")
23
+ end
24
+ end
25
+
26
+
27
+ RuTils::load_component :pluralizer #Выбор числительного и сумма прописью
28
+ RuTils::load_component :gilenson # Гиленсон
29
+ RuTils::load_component :datetime # Дата и время без локалей
30
+ RuTils::load_component :transliteration # Транслит
31
+ RuTils::load_component :integration # Интеграция с rails, textile и тд
32
+ RuTils::load_component :countries # Данные о странах на русском и английском
@@ -0,0 +1,71 @@
1
+ # Реализует транслитерацию "в обе стороны", дающую возможность автоматически использовать URL как ключ записи
2
+ module RuTils::Transliteration::BiDi
3
+ TABLE_TO = {
4
+ "А"=>"A","Б"=>"B","В"=>"V","Г"=>"G","Д"=>"D",
5
+ "Е"=>"E","Ё"=>"JO","Ж"=>"ZH","З"=>"Z","И"=>"I",
6
+ "Й"=>"JJ","К"=>"K","Л"=>"L","М"=>"M","Н"=>"N",
7
+ "О"=>"O","П"=>"P","Р"=>"R","С"=>"S","Т"=>"T",
8
+ "У"=>"U","Ф"=>"F","Х"=>"KH","Ц"=>"C","Ч"=>"CH",
9
+ "Ш"=>"SH","Щ"=>"SHH","Ъ"=>"_~","Ы"=>"Y","Ь"=>"_'",
10
+ "Э"=>"EH","Ю"=>"JU","Я"=>"JA","а"=>"a","б"=>"b",
11
+ "в"=>"v","г"=>"g","д"=>"d","е"=>"e","ё"=>"jo",
12
+ "ж"=>"zh","з"=>"z","и"=>"i","й"=>"jj","к"=>"k",
13
+ "л"=>"l","м"=>"m","н"=>"n","о"=>"o","п"=>"p",
14
+ "р"=>"r","с"=>"s","т"=>"t","у"=>"u","ф"=>"f",
15
+ "х"=>"kh","ц"=>"c","ч"=>"ch","ш"=>"sh","щ"=>"shh",
16
+ "ъ"=>"~","ы"=>"y","ь"=>"'","э"=>"eh","ю"=>"ju",
17
+ "я"=>"ja",
18
+ # " "=>"__","_"=>"__"
19
+ # так сразу не получится, будут проблемы с "Ь"=>"_'"
20
+ }.sort do |one, two|
21
+ two[1].split(//).size <=> one[1].split(//).size
22
+ end
23
+
24
+ TABLE_FROM = TABLE_TO.unshift([" ","__"]).clone
25
+ TABLE_TO.unshift(["_","__"])
26
+
27
+ def self.translify(str, allow_slashes = true)
28
+ slash = allow_slashes ? '/' : '';
29
+
30
+ s = str.clone.gsub(/[^\- _0-9a-zA-ZА-ёЁ#{slash}]/, '')
31
+ lang_fr = s.scan(/[А-ёЁ ]+/)
32
+ lang_fr.each do |fr|
33
+ TABLE_TO.each do | translation |
34
+ fr.gsub!(/#{translation[0]}/, translation[1])
35
+ end
36
+ end
37
+
38
+ lang_sr = s.scan(/[0-9A-Za-z\_\-\.\/\']+/)
39
+
40
+ string = ""
41
+ if s =~ /\A[А-ёЁ ]/
42
+ lang_fr, lang_sr = lang_sr, lang_fr
43
+ string = "+"
44
+ end
45
+
46
+ 0.upto([lang_fr.length, lang_sr.length].min-1) do |x|
47
+ string += lang_sr[x] + "+" + lang_fr[x] + "+";
48
+ end
49
+
50
+ if (lang_fr.length < lang_sr.length)
51
+ string += lang_sr[lang_sr.length-1]
52
+ else
53
+ string[0, string.length-1]
54
+ end
55
+ end
56
+
57
+ def self.detranslify(str, allow_slashes = true)
58
+ slash = allow_slashes ? '/' : '';
59
+
60
+ str.split('/').inject(out = "") do |out, pg|
61
+ strings = pg.split('+')
62
+ 1.step(strings.length-1, 2) do |x|
63
+ TABLE_FROM.each do | translation |
64
+ strings[x].gsub!(/#{translation[1]}/, translation[0])
65
+ end
66
+ end
67
+ out << slash << strings.to_s
68
+ end
69
+ out[slash.length, out.length-slash.length]
70
+ end
71
+ end
@@ -0,0 +1,74 @@
1
+ # Реализует простейшую транслитерацию
2
+ # "вот мы и здесь".translify => "vot my i zdes"
3
+ # "vot my i zdes".detranslify => "вот мы и здесь"
4
+ module RuTils::Transliteration::Simple
5
+ TABLE_LOWER = {
6
+ "і"=>"i","ґ"=>"g","ё"=>"yo","№"=>"#","є"=>"e",
7
+ "ї"=>"yi","а"=>"a","б"=>"b",
8
+ "в"=>"v","г"=>"g","д"=>"d","е"=>"e","ж"=>"zh",
9
+ "з"=>"z","и"=>"i","й"=>"y","к"=>"k","л"=>"l",
10
+ "м"=>"m","н"=>"n","о"=>"o","п"=>"p","р"=>"r",
11
+ "с"=>"s","т"=>"t","у"=>"u","ф"=>"f","х"=>"h",
12
+ "ц"=>"ts","ч"=>"ch","ш"=>"sh","щ"=>"sch","ъ"=>"'",
13
+ "ы"=>"yi","ь"=>"","э"=>"e","ю"=>"yu","я"=>"ya"
14
+ }.sort do | one, two|
15
+ two[1].size <=> one[1].size
16
+ end
17
+
18
+ TABLE_UPPER = {
19
+ "Ґ"=>"G","Ё"=>"YO","Є"=>"E","Ї"=>"YI","І"=>"I",
20
+ "А"=>"A","Б"=>"B","В"=>"V","Г"=>"G",
21
+ "Д"=>"D","Е"=>"E","Ж"=>"ZH","З"=>"Z","И"=>"I",
22
+ "Й"=>"Y","К"=>"K","Л"=>"L","М"=>"M","Н"=>"N",
23
+ "О"=>"O","П"=>"P","Р"=>"R","С"=>"S","Т"=>"T",
24
+ "У"=>"U","Ф"=>"F","Х"=>"H","Ц"=>"TS","Ч"=>"CH",
25
+ "Ш"=>"SH","Щ"=>"SCH","Ъ"=>"'","Ы"=>"YI","Ь"=>"",
26
+ "Э"=>"E","Ю"=>"YU","Я"=>"YA",
27
+ }.sort do | one, two|
28
+ two[1].size <=> one[1].size
29
+ end
30
+
31
+ TABLE = TABLE_UPPER + TABLE_LOWER
32
+
33
+ # Заменяет кириллицу в строке на латиницу. Немного специфично потому что поддерживает
34
+ # комби-регистр (Щука -> Shuka)
35
+ def self.translify(str)
36
+ chars = str.split(//)
37
+
38
+ lowers = TABLE_LOWER.map{|e| e[0] }
39
+ uppers = TABLE_UPPER.map{|e| e[0] }
40
+
41
+ hashtable = {}
42
+ TABLE.each do | item |
43
+ next unless item[0] && item[1]
44
+ hashtable[item[0]] = item[1]
45
+ end
46
+
47
+ result = ''
48
+ chars.each_with_index do | char, index |
49
+ if uppers.include?(char) && lowers.include?(chars[index+1])
50
+ # Combined case. Here we deal with Latin letters so there is no problem to use
51
+ # Ruby's builtin upcase_downcase
52
+ ch = hashtable[char].downcase.capitalize
53
+ result << ch
54
+ elsif uppers.include?(char)
55
+ result << hashtable[char]
56
+ elsif lowers.include?(char)
57
+ result << hashtable[char]
58
+ else
59
+ result << char
60
+ end
61
+ end
62
+ return result
63
+ end
64
+
65
+ # Транслитерирует строку, делая ее пригодной для применения как имя директории или URL
66
+ def self.dirify(string)
67
+ st = self.translify(string)
68
+ st.gsub!(/(\s\&\s)|(\s\&amp\;\s)/, ' and ') # convert & to "and"
69
+ st.gsub!(/\W/, ' ') #replace non-chars
70
+ st.gsub!(/(_)$/, '') #trailing underscores
71
+ st.gsub!(/^(_)/, '') #leading unders
72
+ st.strip.translify.gsub(/(\s)/,'-').downcase.squeeze('-')
73
+ end
74
+ end
@@ -0,0 +1,51 @@
1
+ module RuTils
2
+ module Transliteration #:nodoc:
3
+ end
4
+ end
5
+
6
+ require File.join(File.dirname(__FILE__), 'simple')
7
+ require File.join(File.dirname(__FILE__), 'bidi')
8
+
9
+
10
+ # Реализует транслитерацию любого объекта, реализующего String или to_s
11
+ module RuTils::Transliteration::StringFormatting
12
+
13
+ # Транслитерирует строку в латиницу, и возвращает измененную строку
14
+ def translify
15
+ RuTils::Transliteration::Simple::translify(self.to_s)
16
+ end
17
+
18
+ # Транслитерирует строку, меняя объект
19
+ def translify!
20
+ self.replace(self.translify)
21
+ end
22
+
23
+ # Транслитерирует строку, делая ее пригодной для применения как имя директории или URL
24
+ def dirify
25
+ RuTils::Transliteration::Simple::dirify(self.to_s)
26
+ end
27
+
28
+ # Транслитерирует строку (взаимно-однозначный транслит), и возвращает измененную строку
29
+ def bidi_translify(allow_slashes = true)
30
+ RuTils::Transliteration::BiDi::translify(self.to_s, allow_slashes)
31
+ end
32
+
33
+ # Транслитерирует строку (взаимно-однозначный транслит), меняя объект
34
+ def bidi_translify!(allow_slashes = true)
35
+ self.replace(RuTils::Transliteration::BiDi::translify(self.to_s, allow_slashes))
36
+ end
37
+
38
+ # Заменяет латиницу на кириллицу (взаимно-однозначный транслит), меняя объект
39
+ def bidi_detranslify!(allow_slashes = true)
40
+ self.replace(RuTils::Transliteration::BiDi::detranslify(self.to_s, allow_slashes))
41
+ end
42
+
43
+ # Заменяет латиницу на кириллицу (взаимно-однозначный транслит), и возвращает измененную строку
44
+ def bidi_detranslify(allow_slashes = true)
45
+ RuTils::Transliteration::BiDi::detranslify(self.to_s, allow_slashes)
46
+ end
47
+ end
48
+
49
+ class Object::String
50
+ include RuTils::Transliteration::StringFormatting
51
+ end