turkish_support 0.3.0 → 1.0.0.pre.alpha
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.hound.yml +3 -0
- data/.rubocop.yml +7 -0
- data/README.md +173 -41
- data/Rakefile +3 -3
- data/lib/turkish_support.rb +6 -6
- data/lib/turkish_support/array_methods.rb +5 -1
- data/lib/turkish_support/constants.rb +47 -14
- data/lib/turkish_support/helpers.rb +112 -0
- data/lib/turkish_support/string_methods.rb +33 -21
- data/lib/turkish_support/version.rb +1 -1
- data/spec/helpers_spec.rb +264 -0
- data/spec/turkish_support_spec.rb +482 -122
- data/turkish_support.gemspec +15 -14
- metadata +13 -9
- data/lib/turkish_support/destructives.rb +0 -17
- data/lib/turkish_support/string_helpers.rb +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fca374a0e22cae4752a98bc96a26b64d99e57612
|
4
|
+
data.tar.gz: 5ff3bac0eb61748ec55b9de97f6fed195f15222a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1682d709edeeb141dc55ff93b9243298ae32892d8fe8e5beeabcc4a9b6d9c4800686a9f2a7d8899e52409e557843fd7dc9c37b89d4a072704314c388372809e7
|
7
|
+
data.tar.gz: a90302ff8136ee2ad490f6746cf1043c1fe61a58e750944fe8c5a21c333a4c8b0cab194f8fc6c637b10cfa3710ce9ea338aac4500ce2491bfdcb6d47ff40d16f
|
data/.gitignore
CHANGED
data/.hound.yml
ADDED
data/.rubocop.yml
ADDED
data/README.md
CHANGED
@@ -4,16 +4,41 @@
|
|
4
4
|
[](https://travis-ci.org/sbagdat/turkish_support)
|
5
5
|
[](https://gitter.im/sbagdat/turkish_support)
|
6
6
|
|
7
|
-
Turkish character support for
|
8
|
-
`String#downcase`, `String#capitalize`, `String#swapcase`, `String#casecmp`, `String#match`, `Array#sort`, and their destructive versions like `Array#sort!` or `String#capitalize!`. It also gives you some bonus methods like `String#titleize`.
|
7
|
+
Turkish character support for core ruby methods. This gem provides support nearly all `String` methods, such as `String#upcase`, `String#downcase`, `String#match`, `String#gsub`. It also provides support for `Array#sort`and some bonus methods like `String#titleize`.
|
9
8
|
|
10
9
|
## Requirements
|
11
10
|
|
12
11
|
* Ruby >= 2.0.0
|
13
12
|
* Rails >= 4.0.0
|
14
13
|
|
15
|
-
__Notice:__ TurkishSupport uses refinements instead of monkey patching. Refinements come with Ruby 2.0.0 as a new feature
|
16
|
-
|
14
|
+
__Notice:__ TurkishSupport uses refinements instead of monkey patching. ~~Refinements come with Ruby 2.0.0 as a new feature and also, it is an experimental feature for now. If you want to more information about refinements, you can see the doc at [http://www.ruby-doc.org/core-2.0.0/doc/syntax/refinements_rdoc.html](http://www.ruby-doc.org/core-2.0.0/doc/syntax/refinements_rdoc.html)~~ *Refinements are not an experimental feature, it is a core feature now.*
|
15
|
+
|
16
|
+
* [Installation](#installation)
|
17
|
+
* [Usage](#usage)
|
18
|
+
* [Using with ruby](#using-with-ruby)
|
19
|
+
* [Using with ruby on rails](#using-with-ruby-on-rails)
|
20
|
+
* [Using Core Methods](#using-core-methods)
|
21
|
+
* [String Methods](#string-methods)
|
22
|
+
* [#[] and #[]=](-and-)
|
23
|
+
* [#=~](#-equal-tilda)
|
24
|
+
* [capitalize](#capitalize-and-capitalize)
|
25
|
+
* [casecmp](#casecmp)
|
26
|
+
* [downcase](#downcase-and-downcase)
|
27
|
+
* [gsub](#gsub-and-gsub)
|
28
|
+
* [index](#index)
|
29
|
+
* [match](#match)
|
30
|
+
* [partition](#partition)
|
31
|
+
* [rpartition](#rpartition)
|
32
|
+
* [rindex](#rpartition)
|
33
|
+
* [scan](#scan)
|
34
|
+
* [slice](#slice-and-slice)
|
35
|
+
* [split](#split)
|
36
|
+
* [sub](#sub-and-sub)
|
37
|
+
* [swapcase](#swapcase-and-swapcase)
|
38
|
+
* [titleize](#titleize-and-titleize)
|
39
|
+
* [upcase](#upcase-and-upcase)
|
40
|
+
* [Array Methods](#array-methods)
|
41
|
+
* [sort](sort-and-sort)
|
17
42
|
|
18
43
|
## Installation
|
19
44
|
|
@@ -29,7 +54,7 @@ Or install it yourself as:
|
|
29
54
|
|
30
55
|
$ gem install turkish_support
|
31
56
|
|
32
|
-
## Usage
|
57
|
+
## Usage
|
33
58
|
|
34
59
|
After the installation of the gem, you should follow these steps.
|
35
60
|
|
@@ -59,99 +84,206 @@ class Test
|
|
59
84
|
end
|
60
85
|
end
|
61
86
|
|
62
|
-
Test.new.up_me('içel')
|
87
|
+
Test.new.up_me('içel') # => "İÇEL"
|
63
88
|
```
|
64
89
|
|
65
90
|
### Using with rails
|
66
91
|
|
67
92
|
__Note:__ You don't need to require, because it is already required by the rails.
|
68
93
|
|
69
|
-
*
|
94
|
+
* You must add `using TurkishSupport` line to the top of the scope.
|
70
95
|
|
71
96
|
```ruby
|
72
97
|
using TurkishSupport
|
73
98
|
|
74
|
-
class SampleModel
|
99
|
+
class SampleModel < ActiveRecord::Base
|
75
100
|
...
|
76
101
|
end
|
77
102
|
```
|
78
103
|
|
79
|
-
|
104
|
+
* If you want to use TurkishSupport with a custom class or a module that is not inherited from any rails tie, you must add `using TurkishSupport` line to the class or module.
|
80
105
|
|
81
|
-
|
106
|
+
```ruby
|
107
|
+
class CustomClass
|
108
|
+
using TurkishSupport
|
109
|
+
|
110
|
+
...
|
111
|
+
end
|
112
|
+
```
|
82
113
|
|
83
|
-
|
114
|
+
### Using Core Methods
|
115
|
+
|
116
|
+
If you want to use original set of the core methods in the same scope, you can use `Object#public_send`:
|
84
117
|
|
85
118
|
```ruby
|
86
119
|
str = 'Bağcılar'
|
120
|
+
str.public_send(:upcase) # => "BAğCıLAR"
|
121
|
+
```
|
87
122
|
|
88
|
-
|
89
|
-
str #=> "Bağcılar"
|
123
|
+
## String Methods
|
90
124
|
|
91
|
-
|
92
|
-
|
125
|
+
### [] and []=
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
'Türkiye Cumhuriyeti'[/\w+/] # => "Türkiye"
|
129
|
+
'Çetin'[/[a-ğ]+/i] # => "Çe"
|
93
130
|
```
|
94
131
|
|
95
|
-
|
132
|
+
### =~ (equal-tilda)
|
96
133
|
|
97
134
|
```ruby
|
98
|
-
|
99
|
-
str.downcase #=> "ismail"
|
135
|
+
'Bağlarbaşı Çarşı Kalabalık' =~ (/[s-ü]+/i) # => 8
|
100
136
|
```
|
101
137
|
|
102
|
-
|
138
|
+
### capitalize and capitalize!
|
103
139
|
|
104
140
|
```ruby
|
105
141
|
str = 'türkÇE desteĞİ'
|
106
|
-
|
142
|
+
|
143
|
+
str.capitalize # => "Türkçe desteği"
|
144
|
+
str.capitalize! # => "Türkçe desteği"
|
107
145
|
```
|
108
146
|
|
109
|
-
|
147
|
+
### casecmp
|
148
|
+
|
110
149
|
```ruby
|
111
|
-
'
|
150
|
+
'sıtKI'.casecmp('SITkı') # => 0
|
112
151
|
```
|
113
152
|
|
114
|
-
|
153
|
+
### downcase and downcase!
|
154
|
+
|
115
155
|
```ruby
|
116
|
-
'
|
156
|
+
str = 'İSMAİL'
|
157
|
+
|
158
|
+
str.downcase # => "ismail"
|
159
|
+
str.downcase! # => "ismail"
|
117
160
|
```
|
118
161
|
|
119
|
-
|
162
|
+
### gsub and gsub!
|
120
163
|
|
121
164
|
```ruby
|
122
|
-
|
123
|
-
'Aşağı Ayrancı'.match(/^\w+\s\w+$/) #=> #<MatchData "Aşağı Ayrancı">
|
124
|
-
'aüvvağğ öövvaağ'.match(/^[a-z]+\s[a-z]+$/) #=> #<MatchData "aüvvağğ öövvaağ">
|
125
|
-
'BAĞCIlar'.match(/[A-Z]+/) #=> #<MatchData "BAĞCI">
|
126
|
-
'Aşağı Ayrancı'.match(/\W+/) #=> #<MatchData "">
|
165
|
+
'ağapaşaağa'.gsub(/[a-h]+/, 'bey')
|
127
166
|
```
|
128
167
|
|
129
|
-
|
168
|
+
### index
|
130
169
|
|
131
170
|
```ruby
|
132
|
-
|
133
|
-
|
171
|
+
'?ç-!+*/-ğüı'.index(/\w+/) # => 1
|
172
|
+
'?ç-!+*/-ğüı'.index(/[a-z]+/, 2) # => 8
|
173
|
+
```
|
174
|
+
|
175
|
+
### match
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
'Aşağı'.match(/\w+/)
|
179
|
+
# => #<MatchData "Aşağı">
|
180
|
+
|
181
|
+
'Aşağı Ayrancı'.match(/^\w+\s\w+$/)
|
182
|
+
# => #<MatchData "Aşağı Ayrancı">
|
183
|
+
|
184
|
+
'aüvvağğ öövvaağ'.match(/^[a-z]+\s[a-z]+$/)
|
185
|
+
# => #<MatchData "aüvvağğ öövvaağ">
|
186
|
+
|
187
|
+
'BAĞCIlar'.match(/[A-Z]+/)
|
188
|
+
# => #<MatchData "BAĞCI">
|
189
|
+
|
190
|
+
'Aşağı Ayrancı'.match(/\W+/)
|
191
|
+
# => #<MatchData "">
|
192
|
+
```
|
193
|
+
|
194
|
+
### partition
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
'Bağlarbaşı Çarşı'.partition(/\W+/) # => ["Bağlarbaşı", " ", "Çarşı"]
|
198
|
+
```
|
199
|
+
|
200
|
+
### rpartition
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
'Bağlarbaşı Çarşı Kalabalık'.rpartition(/\W+/)
|
204
|
+
# => ["Bağlarbaşı Çarşı", " ", "Kalabalık"]
|
205
|
+
```
|
206
|
+
|
207
|
+
### rindex
|
208
|
+
|
209
|
+
```ruby
|
210
|
+
'şç-!+*/-ğüı'.rindex(/\w+/, 7) # => 1
|
134
211
|
```
|
135
212
|
|
136
|
-
|
213
|
+
### scan
|
137
214
|
|
138
|
-
|
215
|
+
```ruby
|
216
|
+
'Bağlarbaşı Çarşı Kalabalık'.scan(/[a-z]+/i)
|
217
|
+
# => ["Bağlarbaşı", "Çarşı", "Kalabalık"]
|
218
|
+
```
|
219
|
+
|
220
|
+
|
221
|
+
### slice and slice!
|
139
222
|
|
140
223
|
```ruby
|
141
|
-
'
|
224
|
+
'Duayen'.slice(/[^h-ö]+/) # => "Duaye"
|
225
|
+
```
|
226
|
+
|
227
|
+
### split
|
228
|
+
|
229
|
+
```ruby
|
230
|
+
'Bağlarbaşı Çarşı Kalabalık'.split(/\W+/)
|
231
|
+
# => ["Bağlarbaşı", "Çarşı", "Kalabalık"]
|
232
|
+
|
233
|
+
'Bağlarbaşı Çarşı Kalabalık'.split(/[ç-ş]+/)
|
234
|
+
# => ["Ba", "a", "ba", " Ça", " Ka", "aba"]
|
235
|
+
```
|
236
|
+
|
237
|
+
### sub and sub!
|
238
|
+
|
239
|
+
```ruby
|
240
|
+
'ağapaşaağa'.sub(/[a-h]+/, 'bey') # => "beypaşaağa"
|
241
|
+
```
|
242
|
+
|
243
|
+
### swapcase and swapcase!
|
244
|
+
|
245
|
+
```ruby
|
246
|
+
'TuğÇE'.swapcase # => "tUĞçe"
|
247
|
+
'TuğÇE'.swapcase! # => "tUĞçe"
|
248
|
+
```
|
249
|
+
|
250
|
+
### titleize and titleize!
|
251
|
+
|
252
|
+
*These methods are not core methods of ruby, but they are accepted as useful in most situations.*
|
253
|
+
|
254
|
+
```ruby
|
255
|
+
'türkÇE desteĞİ'.titleize # => "Türkçe Desteği"
|
256
|
+
'türkÇE desteĞİ'.titleize! # => "Türkçe Desteği"
|
142
257
|
|
143
258
|
# Parenthesis, quotes, etc. support
|
144
|
-
"rUBY roCkS... (really! 'tRUSt' ME)".titleize
|
259
|
+
"rUBY roCkS... (really! 'tRUSt' ME)".titleize
|
260
|
+
# => "Ruby Rocks... (Really! 'Trust' Me)"
|
145
261
|
|
146
|
-
# If you don't want to capitalize conjuctions,
|
147
|
-
|
262
|
+
# If you don't want to capitalize conjuctions,
|
263
|
+
# simply pass a false value as parameter
|
264
|
+
"kerem VE aslı VeYa leyla İlE mecnun".titleize(false)
|
265
|
+
# => "Kerem ve Aslı veya Leyla ile Mecnun"
|
148
266
|
```
|
149
267
|
|
150
|
-
|
268
|
+
### upcase and upcase!
|
151
269
|
|
152
270
|
```ruby
|
153
271
|
str = 'Bağcılar'
|
154
|
-
|
272
|
+
|
273
|
+
str.upcase # => "BAĞCILAR"
|
274
|
+
str # => "Bağcılar"
|
275
|
+
|
276
|
+
str.upcase! # => "BAĞCILAR"
|
277
|
+
str # => "BAĞCILAR"
|
278
|
+
```
|
279
|
+
|
280
|
+
## Array Methods
|
281
|
+
|
282
|
+
### sort and sort!
|
283
|
+
|
284
|
+
```ruby
|
285
|
+
%w(iki üç dört ılık iğne iyne).sort
|
286
|
+
# => ["dört", "ılık", "iğne", "iki", "iyne", "üç"]
|
155
287
|
```
|
156
288
|
|
157
289
|
## Contributing
|
data/Rakefile
CHANGED
data/lib/turkish_support.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
|
5
|
-
require
|
6
|
-
require
|
1
|
+
require 'turkish_support/version'
|
2
|
+
require 'turkish_support/constants'
|
3
|
+
require 'turkish_support/helpers'
|
4
|
+
|
5
|
+
require 'turkish_support/string_methods'
|
6
|
+
require 'turkish_support/array_methods'
|
7
7
|
|
8
8
|
module TurkishSupport
|
9
9
|
end
|
@@ -3,11 +3,15 @@ module TurkishSupport
|
|
3
3
|
def sort
|
4
4
|
sort_by do |item|
|
5
5
|
if item.is_a?(String)
|
6
|
-
item.chars.map { |ch|
|
6
|
+
item.chars.map { |ch| ALPHABET.index(ch) }
|
7
7
|
else
|
8
8
|
super
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
12
|
+
|
13
|
+
def sort!
|
14
|
+
replace(sort)
|
15
|
+
end
|
12
16
|
end
|
13
17
|
end
|
@@ -1,21 +1,54 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
module TurkishSupportHelpers
|
2
|
+
ALPHA = {
|
3
|
+
lower: 'abcçdefgğhıijklmnoöpqrsştuüvwxyz',
|
4
|
+
upper: 'ABCÇDEFGĞHIİJKLMNOÖPQRSŞTUÜVWXYZ',
|
5
|
+
tr_lower: 'çğıiöşü',
|
6
|
+
tr_upper: 'ÇĞIİÖŞÜ'
|
7
|
+
}
|
8
8
|
|
9
|
-
|
10
|
-
DESTRUCTIVE_ARRAY_METHODS = %i(sort)
|
9
|
+
ALPHABET = ALPHA[:upper] + ALPHA[:lower]
|
11
10
|
|
12
|
-
|
11
|
+
META_CHARS = {
|
13
12
|
'\w' => '[\p{Latin}\d_]',
|
14
|
-
'\W' => '[^\p{Latin}\d_]'
|
15
|
-
'a-z' => DOWNCASED_ALPHABET,
|
16
|
-
'A-Z' => UPCASED_ALPHABET
|
13
|
+
'\W' => '[^\p{Latin}\d_]'
|
17
14
|
}
|
18
15
|
|
16
|
+
# Regexp required methods
|
17
|
+
RE_RE_METHS = %i(
|
18
|
+
match
|
19
|
+
scan
|
20
|
+
)
|
21
|
+
|
22
|
+
# Regexp optional methods
|
23
|
+
RE_OP_METHS = %i(
|
24
|
+
[]
|
25
|
+
[]=
|
26
|
+
=~
|
27
|
+
index
|
28
|
+
rindex
|
29
|
+
partition
|
30
|
+
rpartition
|
31
|
+
slice
|
32
|
+
slice!
|
33
|
+
split
|
34
|
+
sub
|
35
|
+
sub!
|
36
|
+
gsub
|
37
|
+
gsub!
|
38
|
+
)
|
39
|
+
|
40
|
+
CASE_RELATED_METHS = %i(
|
41
|
+
downcase
|
42
|
+
downcase!
|
43
|
+
upcase
|
44
|
+
upcase!
|
45
|
+
capitalize
|
46
|
+
capitalize!
|
47
|
+
)
|
48
|
+
|
49
|
+
RANGE_REGEXP = /\[[^\]]*?([#{ALPHABET}]-[#{ALPHABET}])[^\[]*?\]/
|
50
|
+
|
19
51
|
CONJUCTIONS = %w(ve ile veya)
|
20
|
-
|
52
|
+
|
53
|
+
SPECIAL_CHARS = %q{("'}
|
21
54
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module TurkishSupportHelpers
|
2
|
+
def translate_regexp(pattern) # rubocop:disable Metrics/AbcSize
|
3
|
+
Regexp.new(pattern) unless pattern.is_a? Regexp
|
4
|
+
re, options = pattern.source, pattern.options
|
5
|
+
|
6
|
+
while re.match(RANGE_REGEXP)
|
7
|
+
re.scan(RANGE_REGEXP).flatten.compact.each do |matching|
|
8
|
+
re.gsub! matching, translate_range(matching, pattern.casefold?)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
META_CHARS.each { |k, v| re.gsub!(k, v) }
|
13
|
+
Regexp.new(re.force_encoding('UTF-8'), Regexp::FIXEDENCODING | options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def translate_range(range_as_string, casefold = false)
|
17
|
+
return '' unless range_as_string
|
18
|
+
|
19
|
+
range_as_string.gsub!(/\[\]/, '')
|
20
|
+
first, last = range_as_string.split('-')
|
21
|
+
|
22
|
+
expand_range(first, last, casefold)
|
23
|
+
end
|
24
|
+
|
25
|
+
def prepare_for(meth, string)
|
26
|
+
valid_meths = %i(upcase downcase capitalize)
|
27
|
+
unless valid_meths.include?(meth) && string.is_a?(String)
|
28
|
+
fail ArgumentError, 'Invalid arguments for method `prepare_for`!'
|
29
|
+
end
|
30
|
+
|
31
|
+
method("prepare_for_#{meth}").call(string)
|
32
|
+
end
|
33
|
+
|
34
|
+
def tr_char?(ch)
|
35
|
+
tr_lower?(ch) || tr_upper?(ch)
|
36
|
+
end
|
37
|
+
|
38
|
+
def tr_lower?(ch)
|
39
|
+
ALPHA[:tr_lower].include? ch
|
40
|
+
end
|
41
|
+
|
42
|
+
def tr_upper?(ch)
|
43
|
+
ALPHA[:tr_upper].include? ch
|
44
|
+
end
|
45
|
+
|
46
|
+
def conjuction?(string)
|
47
|
+
CONJUCTIONS.include? string
|
48
|
+
end
|
49
|
+
|
50
|
+
def start_with_a_special_char?(string)
|
51
|
+
string =~ /^[#{SPECIAL_CHARS}]/
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def prepare_for_upcase(string)
|
57
|
+
string.tr(ALPHA[:tr_lower], ALPHA[:tr_upper])
|
58
|
+
end
|
59
|
+
|
60
|
+
def prepare_for_downcase(string)
|
61
|
+
string.tr(ALPHA[:tr_upper], ALPHA[:tr_lower])
|
62
|
+
end
|
63
|
+
|
64
|
+
def prepare_for_capitalize(string)
|
65
|
+
[
|
66
|
+
prepare_for(:upcase, string.chr).upcase,
|
67
|
+
prepare_for(:downcase, self[1..-1]).downcase
|
68
|
+
].join
|
69
|
+
end
|
70
|
+
|
71
|
+
def expand_range(first, last, casefold)
|
72
|
+
if lower.include?(first) && lower.include?(last)
|
73
|
+
downcase_range(first, last, casefold)
|
74
|
+
elsif upper.include?(first) && upper.include?(last)
|
75
|
+
upcase_range(first, last, casefold)
|
76
|
+
else
|
77
|
+
fail ArgumentError, 'Invalid regexp range arguments!'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def downcase_range(first, last, casefold)
|
82
|
+
lower(first, last) +
|
83
|
+
(lower_opposite(first, last) if casefold).to_s
|
84
|
+
end
|
85
|
+
|
86
|
+
def upcase_range(first, last, casefold)
|
87
|
+
upper(first, last) +
|
88
|
+
(upper_opposite(first, last) if casefold).to_s
|
89
|
+
end
|
90
|
+
|
91
|
+
def lower(first = nil, last = nil)
|
92
|
+
return ALPHA[:lower] if first.nil? || last.nil?
|
93
|
+
ALPHA[:lower][ALPHA[:lower].index(first)..ALPHA[:lower].index(last)]
|
94
|
+
end
|
95
|
+
|
96
|
+
def lower_opposite(first, last)
|
97
|
+
upper[lower.index(first)..lower.index(last)].delete("^#{ALPHA[:tr_upper]}")
|
98
|
+
end
|
99
|
+
|
100
|
+
def upper(first = nil, last = nil)
|
101
|
+
return ALPHA[:upper] if first.nil? || last.nil?
|
102
|
+
ALPHA[:upper][ALPHA[:upper].index(first)..ALPHA[:upper].index(last)]
|
103
|
+
end
|
104
|
+
|
105
|
+
def upper_opposite(first, last)
|
106
|
+
lower[upper.index(first)..upper.index(last)].delete("^#{ALPHA[:tr_lower]}")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
module TurkishSupport
|
111
|
+
include TurkishSupportHelpers
|
112
|
+
end
|