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.
- data/CHANGELOG +110 -0
- data/README +202 -0
- data/Rakefile.rb +128 -0
- data/TODO +11 -0
- data/bin/gilensize +18 -0
- data/bin/rutilize +38 -0
- data/init.rb +6 -0
- data/lib/countries/countries.rb +1772 -0
- data/lib/datetime/datetime.rb +87 -0
- data/lib/gilenson/gilenson.rb +642 -0
- data/lib/gilenson/gilenson_port.rb +321 -0
- data/lib/integration/blue_cloth_override.rb +12 -0
- data/lib/integration/integration.rb +32 -0
- data/lib/integration/rails_date_helper_override.rb +113 -0
- data/lib/integration/red_cloth_override.rb +27 -0
- data/lib/pluralizer/pluralizer.rb +236 -0
- data/lib/rutils.rb +32 -0
- data/lib/transliteration/bidi.rb +71 -0
- data/lib/transliteration/simple.rb +74 -0
- data/lib/transliteration/transliteration.rb +51 -0
- data/test/run_tests.rb +4 -0
- data/test/t_datetime.rb +42 -0
- data/test/t_gilenson.rb +371 -0
- data/test/t_integration.rb +125 -0
- data/test/t_pluralize.rb +69 -0
- data/test/t_rutils_base.rb +10 -0
- data/test/t_transliteration.rb +109 -0
- data/test/t_typografica.rb +57 -0
- metadata +92 -0
@@ -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
|
data/lib/rutils.rb
ADDED
@@ -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\&\;\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
|