rotuka-rutils 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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