rutils 1.1.4 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemtest +0 -0
- data/History.txt +10 -0
- data/Manifest.txt +4 -8
- data/README.txt +20 -172
- data/Rakefile.rb +5 -11
- data/init.rb +3 -3
- data/lib/{gilenson/gilenson_stub.rb → gilenson_stub.rb} +0 -6
- data/lib/integration/integration.rb +1 -1
- data/lib/integration/rails_date_helper_override.rb +4 -4
- data/lib/pluralizer.rb +101 -0
- data/lib/rudates.rb +85 -0
- data/lib/rutils.rb +13 -7
- data/lib/transliteration.rb +30 -0
- data/lib/version.rb +1 -1
- data/test/extras/integration_rails_filter.rb +1 -1
- data/test/extras/integration_rails_gilenson_helpers.rb +1 -1
- data/test/extras/integration_rails_helpers.rb +1 -1
- data/test/run_tests.rb +1 -1
- data/test/test_datetime.rb +16 -7
- data/test/test_integration.rb +1 -1
- data/test/test_integration_flag.rb +1 -1
- data/test/test_pluralize.rb +1 -1
- data/test/test_rutils_base.rb +1 -1
- data/test/test_transliteration.rb +1 -32
- metadata +45 -32
- data/bin/rutilize +0 -38
- data/lib/countries/countries.rb +0 -1773
- data/lib/datetime/datetime.rb +0 -83
- data/lib/pluralizer/pluralizer.rb +0 -288
- data/lib/transliteration/bidi.rb +0 -21
- data/lib/transliteration/simple.rb +0 -75
- data/lib/transliteration/transliteration.rb +0 -79
data/lib/datetime/datetime.rb
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
module RuTils
|
3
|
-
module DateTime
|
4
|
-
|
5
|
-
def self.distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, absolute = false) #nodoc
|
6
|
-
from_time = from_time.to_time if from_time.respond_to?(:to_time)
|
7
|
-
to_time = to_time.to_time if to_time.respond_to?(:to_time)
|
8
|
-
distance_in_minutes = (((to_time - from_time).abs)/60).round
|
9
|
-
distance_in_seconds = ((to_time - from_time).abs).round
|
10
|
-
|
11
|
-
case distance_in_minutes
|
12
|
-
when 0..1
|
13
|
-
return (distance_in_minutes==0) ? 'меньше минуты' : '1 минуту' unless include_seconds
|
14
|
-
|
15
|
-
case distance_in_seconds
|
16
|
-
when 0..5 then 'менее 5 секунд'
|
17
|
-
when 6..10 then 'менее 10 секунд'
|
18
|
-
when 11..20 then 'менее 20 секунд'
|
19
|
-
when 21..40 then 'пол-минуты'
|
20
|
-
when 41..59 then 'меньше минуты'
|
21
|
-
else '1 минуту'
|
22
|
-
end
|
23
|
-
|
24
|
-
when 2..45 then distance_in_minutes.to_s +
|
25
|
-
" " + distance_in_minutes.items("минута", "минуты", "минут")
|
26
|
-
when 46..90 then 'около часа'
|
27
|
-
# исключение, сдвигаем на один влево чтобы соответствовать падежу
|
28
|
-
when 90..1440 then "около " + (distance_in_minutes.to_f / 60.0).round.to_s +
|
29
|
-
" " + (distance_in_minutes.to_f / 60.0).round.items("часа", 'часов', 'часов')
|
30
|
-
when 1441..2880 then '1 день'
|
31
|
-
else (distance_in_minutes / 1440).round.to_s +
|
32
|
-
" " + (distance_in_minutes / 1440).round.items("день", "дня", "дней")
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.ru_strftime(time, format_str='%d.%m.%Y')
|
37
|
-
clean_fmt = format_str.to_s.gsub(/%{2}/, RuTils::SUBSTITUTION_MARKER).
|
38
|
-
gsub(/%a/, Date::RU_ABBR_DAYNAMES[time.wday]).
|
39
|
-
gsub(/%A/, Date::RU_DAYNAMES[time.wday]).
|
40
|
-
gsub(/%b/, Date::RU_ABBR_MONTHNAMES[time.mon]).
|
41
|
-
gsub(/%d(\s)*%B/, '%02d' % time.day + '\1' + Date::RU_INFLECTED_MONTHNAMES[time.mon]).
|
42
|
-
gsub(/%e(\s)*%B/, '%d' % time.day + '\1' + Date::RU_INFLECTED_MONTHNAMES[time.mon]).
|
43
|
-
gsub(/%B/, Date::RU_MONTHNAMES[time.mon]).
|
44
|
-
gsub(/#{RuTils::SUBSTITUTION_MARKER}/, '%%')
|
45
|
-
|
46
|
-
# Теперь когда все нужные нам маркеры заменены можно отдать это стандартному strftime
|
47
|
-
time.respond_to?(:strftime_norutils) ? time.strftime_norutils(clean_fmt) : time.to_time.strftime_norutils(clean_fmt)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
class Date
|
53
|
-
RU_MONTHNAMES = [nil] + %w{ январь февраль март апрель май июнь июль август сентябрь октябрь ноябрь декабрь }
|
54
|
-
RU_DAYNAMES = %w(воскресенье понедельник вторник среда четверг пятница суббота)
|
55
|
-
RU_ABBR_MONTHNAMES = [nil] + %w{ янв фев мар апр май июн июл авг сен окт ноя дек }
|
56
|
-
RU_ABBR_DAYNAMES = %w(вск пн вт ср чт пт сб)
|
57
|
-
RU_INFLECTED_MONTHNAMES = [nil] + %w{ января февраля марта апреля мая июня июля августа сентября октября ноября декабря }
|
58
|
-
RU_DAYNAMES_E = [nil] + %w{первое второе третье четвёртое пятое шестое седьмое восьмое девятое десятое одиннадцатое двенадцатое тринадцатое четырнадцатое пятнадцатое шестнадцатое семнадцатое восемнадцатое девятнадцатое двадцатое двадцать тридцатое тридцатьпервое}
|
59
|
-
end
|
60
|
-
|
61
|
-
class Time
|
62
|
-
alias_method :strftime_norutils, :strftime
|
63
|
-
|
64
|
-
def strftime(fmt)
|
65
|
-
RuTils::overrides_enabled? ? RuTils::DateTime::ru_strftime(self, fmt) : strftime_norutils(fmt)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
class Date
|
70
|
-
# Inside rails we have date formatting
|
71
|
-
if self.instance_methods.include?('strftime')
|
72
|
-
alias_method :strftime_norutils, :strftime
|
73
|
-
def strftime(fmt='%F')
|
74
|
-
RuTils::overrides_enabled? ? RuTils::DateTime::ru_strftime(self, fmt) : strftime_norutils(fmt)
|
75
|
-
end
|
76
|
-
|
77
|
-
else
|
78
|
-
def strftime(fmt='%F')
|
79
|
-
RuTils::overrides_enabled? ? RuTils::DateTime::ru_strftime(self, fmt) : to_time.strftime(fmt)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
end
|
@@ -1,288 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
module RuTils
|
3
|
-
module Pluralization #:nodoc:
|
4
|
-
# Выбирает нужный падеж существительного в зависимости от числа
|
5
|
-
def self.choose_plural(amount, *variants)
|
6
|
-
variant = (amount%10==1 && amount%100!=11 ? 1 : amount%10>=2 && amount%10<=4 && (amount%100<10 || amount%100>=20) ? 2 : 3)
|
7
|
-
variants[variant-1]
|
8
|
-
end
|
9
|
-
|
10
|
-
# Выводит целое или дробное число как сумму в рублях прописью
|
11
|
-
def self.rublej(amount)
|
12
|
-
pts = []
|
13
|
-
|
14
|
-
pts << RuTils::Pluralization::sum_string(amount.to_i, 1, "рубль", "рубля", "рублей") unless amount.to_i == 0
|
15
|
-
if amount.kind_of?(Float)
|
16
|
-
remainder = (amount.divmod(1)[1]*100).round
|
17
|
-
if (remainder == 100)
|
18
|
-
pts = [RuTils::Pluralization::sum_string(amount.to_i+1, 1, 'рубль', 'рубля', 'рублей')]
|
19
|
-
else
|
20
|
-
pts << RuTils::Pluralization::sum_string(remainder.to_i, 2, 'копейка', 'копейки', 'копеек')
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
pts.join(' ')
|
25
|
-
end
|
26
|
-
|
27
|
-
# Выводит целое или дробное число как сумму в гривнах прописью
|
28
|
-
def self.griven(amount)
|
29
|
-
pts = []
|
30
|
-
|
31
|
-
pts << RuTils::Pluralization::sum_string(amount.to_i, 2, "гривна", "гривны", "гривен") unless amount.to_i == 0
|
32
|
-
if amount.kind_of?(Float)
|
33
|
-
remainder = (amount.divmod(1)[1]*100).round
|
34
|
-
if (remainder == 100)
|
35
|
-
pts = [RuTils::Pluralization::sum_string(amount.to_i+1, 2, 'гривна', 'гривны', 'гривен')]
|
36
|
-
else
|
37
|
-
pts << RuTils::Pluralization::sum_string(remainder.to_i, 2, 'копейка', 'копейки', 'копеек')
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
pts.join(' ')
|
42
|
-
end
|
43
|
-
|
44
|
-
def self.kopeek(amount)
|
45
|
-
pts = []
|
46
|
-
r, k = (amount/100.0).floor, (amount - ((amount/100.0).floor * 100)).to_i
|
47
|
-
pts << RuTils::Pluralization::sum_string(r, 1, "рубль", "рубля", "рублей") unless r.zero?
|
48
|
-
pts << RuTils::Pluralization::sum_string(k, 2, 'копейка', 'копейки', 'копеек') unless k.zero?
|
49
|
-
pts.join(' ')
|
50
|
-
end
|
51
|
-
|
52
|
-
# Выполняет преобразование числа из цифрого вида в символьное
|
53
|
-
# amount - числительное
|
54
|
-
# gender = 1 - мужской, = 2 - женский, = 3 - средний
|
55
|
-
# one_item - именительный падеж единственного числа (= 1)
|
56
|
-
# two_items - родительный падеж единственного числа (= 2-4)
|
57
|
-
# five_items - родительный падеж множественного числа ( = 5-10)
|
58
|
-
def self.sum_string(amount, gender, one_item='', two_items='', five_items='')
|
59
|
-
into = ''
|
60
|
-
tmp_val ||= 0
|
61
|
-
|
62
|
-
return "ноль " + five_items if amount == 0
|
63
|
-
|
64
|
-
tmp_val = amount
|
65
|
-
|
66
|
-
# единицы
|
67
|
-
into, tmp_val = sum_string_fn(into, tmp_val, gender, one_item, two_items, five_items)
|
68
|
-
|
69
|
-
return into if tmp_val == 0
|
70
|
-
|
71
|
-
# тысячи
|
72
|
-
into, tmp_val = sum_string_fn(into, tmp_val, 2, "тысяча", "тысячи", "тысяч")
|
73
|
-
|
74
|
-
return into if tmp_val == 0
|
75
|
-
|
76
|
-
# миллионы
|
77
|
-
into, tmp_val = sum_string_fn(into, tmp_val, 1, "миллион", "миллиона", "миллионов")
|
78
|
-
|
79
|
-
return into if tmp_val == 0
|
80
|
-
|
81
|
-
# миллиардов
|
82
|
-
into, tmp_val = sum_string_fn(into, tmp_val, 1, "миллиард", "миллиарда", "миллиардов")
|
83
|
-
return into
|
84
|
-
end
|
85
|
-
|
86
|
-
private
|
87
|
-
def self.sum_string_fn(into, tmp_val, gender, one_item='', two_items='', five_items='')
|
88
|
-
rest, rest1, end_word, ones, tens, hundreds = [nil]*6
|
89
|
-
#
|
90
|
-
rest = tmp_val % 1000
|
91
|
-
tmp_val = tmp_val / 1000
|
92
|
-
if rest == 0
|
93
|
-
# последние три знака нулевые
|
94
|
-
into = five_items + " " if into == ""
|
95
|
-
return [into, tmp_val]
|
96
|
-
end
|
97
|
-
#
|
98
|
-
# начинаем подсчет с Rest
|
99
|
-
end_word = five_items
|
100
|
-
# сотни
|
101
|
-
hundreds = case rest / 100
|
102
|
-
when 0 then ""
|
103
|
-
when 1 then "сто "
|
104
|
-
when 2 then "двести "
|
105
|
-
when 3 then "триста "
|
106
|
-
when 4 then "четыреста "
|
107
|
-
when 5 then "пятьсот "
|
108
|
-
when 6 then "шестьсот "
|
109
|
-
when 7 then "семьсот "
|
110
|
-
when 8 then "восемьсот "
|
111
|
-
when 9 then "девятьсот "
|
112
|
-
end
|
113
|
-
|
114
|
-
# десятки
|
115
|
-
rest = rest % 100
|
116
|
-
rest1 = rest / 10
|
117
|
-
ones = ""
|
118
|
-
tens = case rest1
|
119
|
-
when 0 then ""
|
120
|
-
when 1 # особый случай
|
121
|
-
case rest
|
122
|
-
when 10 then "десять "
|
123
|
-
when 11 then "одиннадцать "
|
124
|
-
when 12 then "двенадцать "
|
125
|
-
when 13 then "тринадцать "
|
126
|
-
when 14 then "четырнадцать "
|
127
|
-
when 15 then "пятнадцать "
|
128
|
-
when 16 then "шестнадцать "
|
129
|
-
when 17 then "семнадцать "
|
130
|
-
when 18 then "восемнадцать "
|
131
|
-
when 19 then "девятнадцать "
|
132
|
-
end
|
133
|
-
when 2 then "двадцать "
|
134
|
-
when 3 then "тридцать "
|
135
|
-
when 4 then "сорок "
|
136
|
-
when 5 then "пятьдесят "
|
137
|
-
when 6 then "шестьдесят "
|
138
|
-
when 7 then "семьдесят "
|
139
|
-
when 8 then "восемьдесят "
|
140
|
-
when 9 then "девяносто "
|
141
|
-
end
|
142
|
-
#
|
143
|
-
if rest1 < 1 or rest1 > 1 # единицы
|
144
|
-
case rest % 10
|
145
|
-
when 1
|
146
|
-
ones = case gender
|
147
|
-
when 1 then "один "
|
148
|
-
when 2 then "одна "
|
149
|
-
when 3 then "одно "
|
150
|
-
end
|
151
|
-
end_word = one_item
|
152
|
-
when 2
|
153
|
-
if gender == 2
|
154
|
-
ones = "две "
|
155
|
-
else
|
156
|
-
ones = "два "
|
157
|
-
end
|
158
|
-
end_word = two_items
|
159
|
-
when 3
|
160
|
-
ones = "три " if end_word = two_items # TODO - WTF?
|
161
|
-
when 4
|
162
|
-
ones = "четыре " if end_word = two_items # TODO - WTF?
|
163
|
-
when 5
|
164
|
-
ones = "пять "
|
165
|
-
when 6
|
166
|
-
ones = "шесть "
|
167
|
-
when 7
|
168
|
-
ones = "семь "
|
169
|
-
when 8
|
170
|
-
ones = "восемь "
|
171
|
-
when 9
|
172
|
-
ones = "девять "
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
# сборка строки
|
177
|
-
plural = [hundreds, tens, ones, end_word, " ", into].join.strip
|
178
|
-
return [plural, tmp_val]
|
179
|
-
end
|
180
|
-
|
181
|
-
# Реализует вывод прописью любого объекта, реализующего Float
|
182
|
-
module FloatFormatting
|
183
|
-
|
184
|
-
# Выдает сумму прописью с учетом дробной доли. Дробная доля округляется до миллионной, или (если
|
185
|
-
# дробная доля оканчивается на нули) до ближайшей доли ( 500 тысячных округляется до 5 десятых).
|
186
|
-
# Дополнительный аргумент - род существительного (1 - мужской, 2- женский, 3-средний)
|
187
|
-
def propisju(gender = 2)
|
188
|
-
raise "Это не число!" if self.nan?
|
189
|
-
|
190
|
-
st = RuTils::Pluralization::sum_string(self.to_i, gender, "целая", "целых", "целых")
|
191
|
-
|
192
|
-
remainder = self.to_s.match(/\.(\d+)/)[1]
|
193
|
-
|
194
|
-
signs = remainder.to_s.size- 1
|
195
|
-
|
196
|
-
it = [["десятая", "десятых"]]
|
197
|
-
it << ["сотая", "сотых"]
|
198
|
-
it << ["тысячная", "тысячных"]
|
199
|
-
it << ["десятитысячная", "десятитысячных"]
|
200
|
-
it << ["стотысячная", "стотысячных"]
|
201
|
-
it << ["миллионная", "милллионных"]
|
202
|
-
it << ["десятимиллионная", "десятимилллионных", "десятимиллионных"]
|
203
|
-
it << ["стомиллионная", "стомилллионных", "стомиллионных"]
|
204
|
-
it << ["миллиардная", "миллиардных", "миллиардных"]
|
205
|
-
it << ["десятимиллиардная", "десятимиллиардных", "десятимиллиардных"]
|
206
|
-
it << ["стомиллиардная", "стомиллиардных", "стомиллиардных"]
|
207
|
-
it << ["триллионная", "триллионных", "триллионных"]
|
208
|
-
|
209
|
-
while it[signs].nil?
|
210
|
-
remainder = (remainder/10).round
|
211
|
-
signs = remainder.to_s.size- 1
|
212
|
-
end
|
213
|
-
|
214
|
-
suf1, suf2, suf3 = it[signs][0], it[signs][1], it[signs][2]
|
215
|
-
st + " " + RuTils::Pluralization::sum_string(remainder.to_i, 2, suf1, suf2, suf2)
|
216
|
-
end
|
217
|
-
|
218
|
-
def propisju_items(gender=1, *forms)
|
219
|
-
if self == self.to_i
|
220
|
-
return self.to_i.propisju_items(gender, *forms)
|
221
|
-
else
|
222
|
-
self.propisju(gender) + " " + forms[1]
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
end
|
227
|
-
|
228
|
-
# Реализует вывод прописью любого объекта, реализующего Numeric
|
229
|
-
module NumericFormatting
|
230
|
-
# Выбирает корректный вариант числительного в зависимости от рода и числа и оформляет сумму прописью
|
231
|
-
# 234.propisju => "двести сорок три"
|
232
|
-
# 221.propisju(2) => "двести двадцать одна"
|
233
|
-
def propisju(gender = 1)
|
234
|
-
RuTils::Pluralization::sum_string(self, gender, "")
|
235
|
-
end
|
236
|
-
|
237
|
-
def propisju_items(gender=1, *forms)
|
238
|
-
self.propisju(gender) + " " + RuTils::Pluralization::choose_plural(self.to_i, *forms)
|
239
|
-
end
|
240
|
-
|
241
|
-
# Выбирает корректный вариант числительного в зависимости от рода и числа. Например:
|
242
|
-
# * 4.items("колесо", "колеса", "колес") => "колеса"
|
243
|
-
def items(one_item, two_items, five_items)
|
244
|
-
RuTils::Pluralization::choose_plural(self, one_item, two_items, five_items)
|
245
|
-
end
|
246
|
-
|
247
|
-
# Выводит сумму в рублях прописью. Например:
|
248
|
-
# * (15.4).rublej => "пятнадцать рублей сорок копеек"
|
249
|
-
# * 1.rubl => "один рубль"
|
250
|
-
# * (3.14).rublja => "три рубля четырнадцать копеек"
|
251
|
-
def rublej
|
252
|
-
RuTils::Pluralization::rublej(self)
|
253
|
-
end
|
254
|
-
alias :rubl :rublej
|
255
|
-
alias :rublja :rublej
|
256
|
-
|
257
|
-
# Выводит сумму в гривнах прописью. Например:
|
258
|
-
# * (15.4).griven => "пятнадцать гривен сорок копеек"
|
259
|
-
# * 1.grivna => "одна гривна"
|
260
|
-
# * (3.14).grivny => "три гривны четырнадцать копеек"
|
261
|
-
def griven
|
262
|
-
RuTils::Pluralization::griven(self)
|
263
|
-
end
|
264
|
-
alias :grivna :griven
|
265
|
-
alias :grivny :griven
|
266
|
-
end
|
267
|
-
|
268
|
-
module FixnumFormatting
|
269
|
-
def kopeek
|
270
|
-
RuTils::Pluralization.kopeek(self)
|
271
|
-
end
|
272
|
-
alias :kopeika :kopeek
|
273
|
-
alias :kopeiki :kopeek
|
274
|
-
end
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
class Object::Numeric
|
279
|
-
include RuTils::Pluralization::NumericFormatting
|
280
|
-
end
|
281
|
-
|
282
|
-
class Object::Fixnum
|
283
|
-
include RuTils::Pluralization::FixnumFormatting
|
284
|
-
end
|
285
|
-
|
286
|
-
class Object::Float
|
287
|
-
include RuTils::Pluralization::FloatFormatting
|
288
|
-
end
|
data/lib/transliteration/bidi.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
# ++DEPRECATED++ Этот модуль удален и присутствует только для выдачи сообщения об ошибке.
|
3
|
-
module RuTils::Transliteration::BiDi
|
4
|
-
ERR = "Equivalent bidirectional transliteration for URLs is malpractice. BiDi translit has been removed from RuTils"
|
5
|
-
|
6
|
-
extend self
|
7
|
-
|
8
|
-
# ++DEPRECATED++
|
9
|
-
def translify(str, allow_slashes = true)
|
10
|
-
bail!
|
11
|
-
end
|
12
|
-
|
13
|
-
# ++DEPRECATED++
|
14
|
-
def detranslify(str, allow_slashes = true)
|
15
|
-
bail!
|
16
|
-
end
|
17
|
-
|
18
|
-
def bail! #:nodoc:
|
19
|
-
raise RuTils::RemovedFeature, ERR
|
20
|
-
end
|
21
|
-
end
|
@@ -1,75 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
# Реализует простейшую транслитерацию
|
3
|
-
# "вот мы и здесь".translify => "vot my i zdes"
|
4
|
-
# "vot my i zdes".detranslify => "вот мы и здесь"
|
5
|
-
module RuTils::Transliteration::Simple
|
6
|
-
TABLE_LOWER = {
|
7
|
-
"і"=>"i","ґ"=>"g","ё"=>"yo","№"=>"#","є"=>"e",
|
8
|
-
"ї"=>"yi","а"=>"a","б"=>"b",
|
9
|
-
"в"=>"v","г"=>"g","д"=>"d","е"=>"e","ж"=>"zh",
|
10
|
-
"з"=>"z","и"=>"i","й"=>"y","к"=>"k","л"=>"l",
|
11
|
-
"м"=>"m","н"=>"n","о"=>"o","п"=>"p","р"=>"r",
|
12
|
-
"с"=>"s","т"=>"t","у"=>"u","ф"=>"f","х"=>"h",
|
13
|
-
"ц"=>"ts","ч"=>"ch","ш"=>"sh","щ"=>"sch","ъ"=>"'",
|
14
|
-
"ы"=>"yi","ь"=>"","э"=>"e","ю"=>"yu","я"=>"ya"
|
15
|
-
}.sort do | one, two|
|
16
|
-
two[1].size <=> one[1].size
|
17
|
-
end
|
18
|
-
|
19
|
-
TABLE_UPPER = {
|
20
|
-
"Ґ"=>"G","Ё"=>"YO","Є"=>"E","Ї"=>"YI","І"=>"I",
|
21
|
-
"А"=>"A","Б"=>"B","В"=>"V","Г"=>"G",
|
22
|
-
"Д"=>"D","Е"=>"E","Ж"=>"ZH","З"=>"Z","И"=>"I",
|
23
|
-
"Й"=>"Y","К"=>"K","Л"=>"L","М"=>"M","Н"=>"N",
|
24
|
-
"О"=>"O","П"=>"P","Р"=>"R","С"=>"S","Т"=>"T",
|
25
|
-
"У"=>"U","Ф"=>"F","Х"=>"H","Ц"=>"TS","Ч"=>"CH",
|
26
|
-
"Ш"=>"SH","Щ"=>"SCH","Ъ"=>"'","Ы"=>"YI","Ь"=>"",
|
27
|
-
"Э"=>"E","Ю"=>"YU","Я"=>"YA",
|
28
|
-
}.sort do | one, two|
|
29
|
-
two[1].size <=> one[1].size
|
30
|
-
end
|
31
|
-
|
32
|
-
TABLE = TABLE_UPPER + TABLE_LOWER
|
33
|
-
|
34
|
-
# Заменяет кириллицу в строке на латиницу. Немного специфично потому что поддерживает
|
35
|
-
# комби-регистр (Щука -> Shuka)
|
36
|
-
def self.translify(str)
|
37
|
-
chars = str.split(//)
|
38
|
-
|
39
|
-
lowers = TABLE_LOWER.map{|e| e[0] }
|
40
|
-
uppers = TABLE_UPPER.map{|e| e[0] }
|
41
|
-
|
42
|
-
hashtable = {}
|
43
|
-
TABLE.each do | item |
|
44
|
-
next unless item[0] && item[1]
|
45
|
-
hashtable[item[0]] = item[1]
|
46
|
-
end
|
47
|
-
|
48
|
-
result = ''
|
49
|
-
chars.each_with_index do | char, index |
|
50
|
-
if uppers.include?(char) && lowers.include?(chars[index+1])
|
51
|
-
# Combined case. Here we deal with Latin letters so there is no problem to use
|
52
|
-
# Ruby's builtin upcase_downcase
|
53
|
-
ch = hashtable[char].downcase.capitalize
|
54
|
-
result << ch
|
55
|
-
elsif uppers.include?(char)
|
56
|
-
result << hashtable[char]
|
57
|
-
elsif lowers.include?(char)
|
58
|
-
result << hashtable[char]
|
59
|
-
else
|
60
|
-
result << char
|
61
|
-
end
|
62
|
-
end
|
63
|
-
return result
|
64
|
-
end
|
65
|
-
|
66
|
-
# Транслитерирует строку, делая ее пригодной для применения как имя директории или URL
|
67
|
-
def self.dirify(string)
|
68
|
-
st = self.translify(string)
|
69
|
-
st.gsub!(/(\s\&\s)|(\s\&\;\s)/, ' and ') # convert & to "and"
|
70
|
-
st.gsub!(/\W/, ' ') #replace non-chars
|
71
|
-
st.gsub!(/(_)$/, '') #trailing underscores
|
72
|
-
st.gsub!(/^(_)/, '') #leading unders
|
73
|
-
st.strip.translify.gsub(/(\s)/,'-').downcase.squeeze('-')
|
74
|
-
end
|
75
|
-
end
|