babelfish-ruby 1.0.1
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 +7 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +137 -0
- data/Rakefile +25 -0
- data/babelfish.gemspec +27 -0
- data/lib/babelfish-ruby.rb +2 -0
- data/lib/babelfish.rb +289 -0
- data/lib/babelfish/phrase/compiler.rb +70 -0
- data/lib/babelfish/phrase/literal.rb +12 -0
- data/lib/babelfish/phrase/node.rb +14 -0
- data/lib/babelfish/phrase/parser.rb +173 -0
- data/lib/babelfish/phrase/parser_base.rb +73 -0
- data/lib/babelfish/phrase/plural_forms.rb +65 -0
- data/lib/babelfish/phrase/plural_forms_parser.rb +64 -0
- data/lib/babelfish/phrase/pluralizer.rb +409 -0
- data/lib/babelfish/phrase/string_to_compile.rb +8 -0
- data/lib/babelfish/phrase/variable.rb +12 -0
- data/lib/babelfish/version.rb +4 -0
- data/spec/lib/babelfish_spec.rb +105 -0
- data/spec/locales/test.en-US.yml +7 -0
- data/spec/locales/test.ru-RU.yml +9 -0
- data/spec/spec_helper.rb +21 -0
- metadata +147 -0
@@ -0,0 +1,409 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
class Babelfish
|
3
|
+
module Phrase
|
4
|
+
# Babelfish pluralizer.
|
5
|
+
module Pluralizer
|
6
|
+
|
7
|
+
@rules = {}
|
8
|
+
|
9
|
+
def self.add( locales, rule )
|
10
|
+
locales = [ locales ] unless locales.kind_of?(Array)
|
11
|
+
|
12
|
+
locales.each { |locale| @rules[locale] = rule }
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.find_rule( locale )
|
16
|
+
return @rules[locale] if @rules.has_key?(locale)
|
17
|
+
|
18
|
+
locale = @rules.keys.find do |loc|
|
19
|
+
/^#{Regexp.escape(loc)}[\-_]/.match(locale) ? loc : nil
|
20
|
+
end
|
21
|
+
locale = 'en' if locale.nil?
|
22
|
+
|
23
|
+
return @rules[locale]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.is_int( input )
|
27
|
+
return (0 == input % 1)
|
28
|
+
end
|
29
|
+
|
30
|
+
## PLURALIZATION RULES
|
31
|
+
## https://github.com/nodeca/babelfish/blob/master/lib/babelfish/pluralizer.js#L51
|
32
|
+
|
33
|
+
# Azerbaijani, Bambara, Burmese, Chinese, Dzongkha, Georgian, Hungarian, Igbo,
|
34
|
+
# Indonesian, Japanese, Javanese, Kabuverdianu, Kannada, Khmer, Korean,
|
35
|
+
# Koyraboro Senni, Lao, Makonde, Malay, Persian, Root, Sakha, Sango,
|
36
|
+
# Sichuan Yi, Thai, Tibetan, Tonga, Turkish, Vietnamese, Wolof, Yoruba
|
37
|
+
|
38
|
+
add(['az', 'bm', 'my', 'zh', 'dz', 'ka', 'hu', 'ig',
|
39
|
+
'id', 'ja', 'jv', 'kea', 'kn', 'km', 'ko',
|
40
|
+
'ses', 'lo', 'kde', 'ms', 'fa', 'root', 'sah', 'sg',
|
41
|
+
'ii', 'th', 'bo', 'to', 'tr', 'vi', 'wo', 'yo'
|
42
|
+
], lambda { |n|
|
43
|
+
return 0
|
44
|
+
});
|
45
|
+
|
46
|
+
# Manx
|
47
|
+
|
48
|
+
add(['gv'], lambda { |n|
|
49
|
+
m10, m20 = n % 10, n % 20
|
50
|
+
|
51
|
+
if (m10 == 1 || m10 == 2 || m20 == 0) && is_int(n)
|
52
|
+
return 0
|
53
|
+
end
|
54
|
+
|
55
|
+
return 1
|
56
|
+
});
|
57
|
+
|
58
|
+
|
59
|
+
# Central Morocco Tamazight
|
60
|
+
|
61
|
+
add(['tzm'], lambda { |n|
|
62
|
+
if n == 0 || n == 1 || (11 <= n && n <= 99 && is_int(n))
|
63
|
+
return 0
|
64
|
+
end
|
65
|
+
|
66
|
+
return 1
|
67
|
+
});
|
68
|
+
|
69
|
+
|
70
|
+
# Macedonian
|
71
|
+
|
72
|
+
add(['mk'], lambda { |n|
|
73
|
+
if (n % 10 == 1) && (n != 11) && is_int(n)
|
74
|
+
return 0
|
75
|
+
end
|
76
|
+
|
77
|
+
return 1
|
78
|
+
});
|
79
|
+
|
80
|
+
|
81
|
+
# Akan, Amharic, Bihari, Filipino, Gun, Hindi,
|
82
|
+
# Lingala, Malagasy, Northern Sotho, Tagalog, Tigrinya, Walloon
|
83
|
+
|
84
|
+
add(['ak', 'am', 'bh', 'fil', 'guw', 'hi',
|
85
|
+
'ln', 'mg', 'nso', 'tl', 'ti', 'wa'
|
86
|
+
], lambda { |n|
|
87
|
+
return (n == 0 || n == 1) ? 0 : 1;
|
88
|
+
});
|
89
|
+
|
90
|
+
|
91
|
+
# Afrikaans, Albanian, Basque, Bemba, Bengali, Bodo, Bulgarian, Catalan,
|
92
|
+
# Cherokee, Chiga, Danish, Divehi, Dutch, English, Esperanto, Estonian, Ewe,
|
93
|
+
# Faroese, Finnish, Friulian, Galician, Ganda, German, Greek, Gujarati, Hausa,
|
94
|
+
# Hawaiian, Hebrew, Icelandic, Italian, Kalaallisut, Kazakh, Kurdish,
|
95
|
+
# Luxembourgish, Malayalam, Marathi, Masai, Mongolian, Nahuatl, Nepali,
|
96
|
+
# Norwegian, Norwegian Bokmål, Norwegian Nynorsk, Nyankole, Oriya, Oromo,
|
97
|
+
# Papiamento, Pashto, Portuguese, Punjabi, Romansh, Saho, Samburu, Soga,
|
98
|
+
# Somali, Spanish, Swahili, Swedish, Swiss German, Syriac, Tamil, Telugu,
|
99
|
+
# Turkmen, Urdu, Walser, Western Frisian, Zulu
|
100
|
+
|
101
|
+
add(['af', 'sq', 'eu', 'bem', 'bn', 'brx', 'bg', 'ca',
|
102
|
+
'chr', 'cgg', 'da', 'dv', 'nl', 'en', 'eo', 'et', 'ee',
|
103
|
+
'fo', 'fi', 'fur', 'gl', 'lg', 'de', 'el', 'gu', 'ha',
|
104
|
+
'haw', 'he', 'is', 'it', 'kl', 'kk', 'ku',
|
105
|
+
'lb', 'ml', 'mr', 'mas', 'mn', 'nah', 'ne',
|
106
|
+
'no', 'nb', 'nn', 'nyn', 'or', 'om',
|
107
|
+
'pap', 'ps', 'pt', 'pa', 'rm', 'ssy', 'saq', 'xog',
|
108
|
+
'so', 'es', 'sw', 'sv', 'gsw', 'syr', 'ta', 'te',
|
109
|
+
'tk', 'ur', 'wae', 'fy', 'zu'
|
110
|
+
], lambda { |n|
|
111
|
+
return (1 == n) ? 0 : 1;
|
112
|
+
});
|
113
|
+
|
114
|
+
|
115
|
+
# Latvian
|
116
|
+
|
117
|
+
add(['lv'], lambda { |n|
|
118
|
+
if n == 0
|
119
|
+
return 0
|
120
|
+
end
|
121
|
+
|
122
|
+
if (n % 10 == 1) && (n % 100 != 11) && is_int(n)
|
123
|
+
return 1
|
124
|
+
end
|
125
|
+
|
126
|
+
return 2
|
127
|
+
});
|
128
|
+
|
129
|
+
|
130
|
+
# Colognian
|
131
|
+
|
132
|
+
add(['ksh'], lambda { |n|
|
133
|
+
return (n == 0) ? 0 : ((n == 1) ? 1 : 2);
|
134
|
+
});
|
135
|
+
|
136
|
+
|
137
|
+
# Cornish, Inari Sami, Inuktitut, Irish, Lule Sami, Northern Sami,
|
138
|
+
# Sami Language, Skolt Sami, Southern Sami
|
139
|
+
|
140
|
+
add(['kw', 'smn', 'iu', 'ga', 'smj', 'se',
|
141
|
+
'smi', 'sms', 'sma'
|
142
|
+
], lambda { |n|
|
143
|
+
return (n == 1) ? 0 : ((n == 2) ? 1 : 2);
|
144
|
+
});
|
145
|
+
|
146
|
+
|
147
|
+
# Belarusian, Bosnian, Croatian, Russian, Serbian, Serbo-Croatian, Ukrainian
|
148
|
+
|
149
|
+
add(['be', 'bs', 'hr', 'ru', 'sr', 'sh', 'uk'], lambda { |n|
|
150
|
+
m10, m100 = n % 10, n % 100
|
151
|
+
|
152
|
+
unless is_int(n)
|
153
|
+
return 3
|
154
|
+
end
|
155
|
+
|
156
|
+
# one → n mod 10 is 1 and n mod 100 is not 11;
|
157
|
+
if 1 == m10 && 11 != m100
|
158
|
+
return 0
|
159
|
+
end
|
160
|
+
|
161
|
+
# few → n mod 10 in 2..4 and n mod 100 not in 12..14;
|
162
|
+
if 2 <= m10 && m10 <= 4 && !(12 <= m100 && m100 <= 14)
|
163
|
+
return 1
|
164
|
+
end
|
165
|
+
|
166
|
+
## many → n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14;
|
167
|
+
## if 0 === m10 || (5 <= m10 && m10 <= 9) || (11 <= m100 && m100 <= 14)
|
168
|
+
## return 2
|
169
|
+
##end
|
170
|
+
|
171
|
+
## other
|
172
|
+
## return 3
|
173
|
+
return 2
|
174
|
+
});
|
175
|
+
|
176
|
+
|
177
|
+
# Polish
|
178
|
+
|
179
|
+
add(['pl'], lambda { |n|
|
180
|
+
m10, m100 = n % 10, n % 100
|
181
|
+
|
182
|
+
unless is_int(n)
|
183
|
+
return 3
|
184
|
+
end
|
185
|
+
|
186
|
+
# one → n is 1;
|
187
|
+
if n == 1
|
188
|
+
return 0
|
189
|
+
end
|
190
|
+
|
191
|
+
# few → n mod 10 in 2..4 and n mod 100 not in 12..14;
|
192
|
+
if 2 <= m10 && m10 <= 4 && !(12 <= m100 && m100 <= 14)
|
193
|
+
return 1
|
194
|
+
end
|
195
|
+
|
196
|
+
# many → n is not 1 and n mod 10 in 0..1 or
|
197
|
+
# n mod 10 in 5..9 or n mod 100 in 12..14
|
198
|
+
# (all other except partials)
|
199
|
+
return 2
|
200
|
+
});
|
201
|
+
|
202
|
+
|
203
|
+
# Lithuanian
|
204
|
+
|
205
|
+
add(['lt'], lambda { |n|
|
206
|
+
m10, m100 = n % 10, n % 100
|
207
|
+
|
208
|
+
unless is_int(n)
|
209
|
+
return 2
|
210
|
+
end
|
211
|
+
|
212
|
+
# one → n mod 10 is 1 and n mod 100 not in 11..19
|
213
|
+
if m10 == 1 && !(11 <= m100 && m100 <= 19)
|
214
|
+
return 0
|
215
|
+
end
|
216
|
+
|
217
|
+
# few → n mod 10 in 2..9 and n mod 100 not in 11..19
|
218
|
+
if 2 <= m10 && m10 <= 9 && !(11 <= m100 && m100 <= 19)
|
219
|
+
return 1
|
220
|
+
end
|
221
|
+
|
222
|
+
# other
|
223
|
+
return 2
|
224
|
+
});
|
225
|
+
|
226
|
+
|
227
|
+
# Tachelhit
|
228
|
+
|
229
|
+
add(['shi'], lambda { |n|
|
230
|
+
return (0 <= n && n <= 1) ? 0 : ((is_int(n) && 2 <= n && n <= 10) ? 1 : 2);
|
231
|
+
});
|
232
|
+
|
233
|
+
|
234
|
+
# Moldavian, Romanian
|
235
|
+
|
236
|
+
add(['mo', 'ro'], lambda { |n|
|
237
|
+
m100 = n % 100;
|
238
|
+
|
239
|
+
unless is_int(n)
|
240
|
+
return 2
|
241
|
+
end
|
242
|
+
|
243
|
+
# one → n is 1
|
244
|
+
if n == 1
|
245
|
+
return 0
|
246
|
+
end
|
247
|
+
|
248
|
+
# few → n is 0 OR n is not 1 AND n mod 100 in 1..19
|
249
|
+
if n == 0 || (1 <= m100 && m100 <= 19)
|
250
|
+
return 1
|
251
|
+
end
|
252
|
+
|
253
|
+
# other
|
254
|
+
return 2
|
255
|
+
});
|
256
|
+
|
257
|
+
|
258
|
+
## Czech, Slovak
|
259
|
+
|
260
|
+
add(['cs', 'sk'], lambda { |n|
|
261
|
+
# one → n is 1
|
262
|
+
if n == 1
|
263
|
+
return 0
|
264
|
+
end
|
265
|
+
|
266
|
+
# few → n in 2..4
|
267
|
+
if n == 2 || n == 3 || n == 4
|
268
|
+
return 1
|
269
|
+
end
|
270
|
+
|
271
|
+
# other
|
272
|
+
return 2
|
273
|
+
});
|
274
|
+
|
275
|
+
|
276
|
+
|
277
|
+
# Slovenian
|
278
|
+
|
279
|
+
add(['sl'], lambda { |n|
|
280
|
+
m100 = n % 100;
|
281
|
+
|
282
|
+
unless is_int(n)
|
283
|
+
return 3
|
284
|
+
end
|
285
|
+
|
286
|
+
# one → n mod 100 is 1
|
287
|
+
if m100 == 1
|
288
|
+
return 0
|
289
|
+
end
|
290
|
+
|
291
|
+
# one → n mod 100 is 2
|
292
|
+
if m100 == 2
|
293
|
+
return 1
|
294
|
+
end
|
295
|
+
|
296
|
+
# one → n mod 100 in 3..4
|
297
|
+
if m100 == 3 || m100 == 4
|
298
|
+
return 2
|
299
|
+
end
|
300
|
+
|
301
|
+
# other
|
302
|
+
return 3
|
303
|
+
});
|
304
|
+
|
305
|
+
|
306
|
+
# Maltese
|
307
|
+
|
308
|
+
add(['mt'], lambda { |n|
|
309
|
+
m100 = n % 100;
|
310
|
+
|
311
|
+
unless is_int(n)
|
312
|
+
return 3
|
313
|
+
end
|
314
|
+
|
315
|
+
# one → n is 1
|
316
|
+
if n == 1
|
317
|
+
return 0
|
318
|
+
end
|
319
|
+
|
320
|
+
# few → n is 0 or n mod 100 in 2..10
|
321
|
+
if n == 0 || (2 <= m100 && m100 <= 10)
|
322
|
+
return 1
|
323
|
+
end
|
324
|
+
|
325
|
+
# many → n mod 100 in 11..19
|
326
|
+
if 11 <= m100 && m100 <= 19
|
327
|
+
return 2
|
328
|
+
end
|
329
|
+
|
330
|
+
# other
|
331
|
+
return 3
|
332
|
+
});
|
333
|
+
|
334
|
+
|
335
|
+
# Arabic
|
336
|
+
|
337
|
+
add(['ar'], lambda { |n|
|
338
|
+
m100 = n % 100;
|
339
|
+
|
340
|
+
unless is_int(n)
|
341
|
+
return 5
|
342
|
+
end
|
343
|
+
|
344
|
+
if n == 0
|
345
|
+
return 0
|
346
|
+
end
|
347
|
+
if n == 1
|
348
|
+
return 1
|
349
|
+
end
|
350
|
+
if n == 2
|
351
|
+
return 2
|
352
|
+
end
|
353
|
+
|
354
|
+
# few → n mod 100 in 3..10
|
355
|
+
if 3 <= m100 && m100 <= 10
|
356
|
+
return 3
|
357
|
+
end
|
358
|
+
|
359
|
+
# many → n mod 100 in 11..99
|
360
|
+
if 11 <= m100 && m100 <= 99
|
361
|
+
return 4
|
362
|
+
end
|
363
|
+
|
364
|
+
# other
|
365
|
+
return 5
|
366
|
+
});
|
367
|
+
|
368
|
+
|
369
|
+
# Breton, Welsh
|
370
|
+
|
371
|
+
add(['br', 'cy'], lambda { |n|
|
372
|
+
if n == 0
|
373
|
+
return 0
|
374
|
+
end
|
375
|
+
if n == 1
|
376
|
+
return 1
|
377
|
+
end
|
378
|
+
if n == 2
|
379
|
+
return 2
|
380
|
+
end
|
381
|
+
if n == 3
|
382
|
+
return 3
|
383
|
+
end
|
384
|
+
if n == 6
|
385
|
+
return 4
|
386
|
+
end
|
387
|
+
|
388
|
+
return 5
|
389
|
+
});
|
390
|
+
|
391
|
+
|
392
|
+
## FRACTIONAL PARTS - SPECIAL CASES
|
393
|
+
|
394
|
+
# French, Fulah, Kabyle
|
395
|
+
|
396
|
+
add(['fr', 'ff', 'kab'], lambda { |n|
|
397
|
+
return (0 <= n && n < 2) ? 0 : 1;
|
398
|
+
});
|
399
|
+
|
400
|
+
|
401
|
+
# Langi
|
402
|
+
|
403
|
+
add(['lag'], lambda { |n|
|
404
|
+
return (n == 0) ? 0 : ((0 < n && n < 2) ? 1 : 2);
|
405
|
+
});
|
406
|
+
|
407
|
+
end
|
408
|
+
end
|
409
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'babelfish'
|
3
|
+
|
4
|
+
describe "Babelfish" do
|
5
|
+
before :all do
|
6
|
+
@b = Babelfish.new({
|
7
|
+
dirs: [ File.expand_path('../locales', File.dirname(__FILE__)) ],
|
8
|
+
default_locale: 'en-US',
|
9
|
+
})
|
10
|
+
end
|
11
|
+
describe "en-US locale" do
|
12
|
+
before :all do
|
13
|
+
@b.locale = 'en-US'
|
14
|
+
end
|
15
|
+
|
16
|
+
describe :t do
|
17
|
+
it "should return placeholder if has no key" do
|
18
|
+
expect( @b.t("wow") ).to eq "[wow]"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should test dummy parameters" do
|
22
|
+
expect(@b.t('test.simple', { dummy: ' test script '})).to eq 'I am '
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should test dummy key" do
|
26
|
+
expect(@b.t('test.dummy_key', { who: 'test script'})).to eq '[test.dummy_key]'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should test simple var" do
|
30
|
+
expect(@b.t('test.simple', { who: 'test script'})).to eq 'I am test script'
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "test.plural.case1" do
|
34
|
+
it "for 2" do
|
35
|
+
expect(@b.t('test.case1.combine', { single: { test: { deep: 'example'} }, count: 10, test:2 })).to eq 'I have 10 nails for example for 2 tests'
|
36
|
+
end
|
37
|
+
|
38
|
+
it "for 10" do
|
39
|
+
expect(@b.t('test.plural.case1', { test: 10 })).to eq 'I have 10 nails'
|
40
|
+
end
|
41
|
+
|
42
|
+
it "for 1" do
|
43
|
+
expect(@b.t('test.plural.case1', { test: 1 })).to eq 'I have 1 nail'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "test.plural.case2" do
|
48
|
+
it "for 1" do
|
49
|
+
expect(@b.t('test.plural.case2', { test: 1 })).to eq 'I have 1 nail simple using'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "test.plural.case3" do
|
54
|
+
it "for 17" do
|
55
|
+
expect(@b.t('test.plural.case3', 17)).to eq 'I have 17 big nails'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe :has_any_value do
|
61
|
+
|
62
|
+
describe "test.plural.case1" do
|
63
|
+
it :exists do
|
64
|
+
expect(@b.has_any_value('test.case1.combine')).to eq true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "test.plural.case2" do
|
69
|
+
it :exists do
|
70
|
+
expect(@b.has_any_value('test.plural.case2')).to eq true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "test.plural.case3" do
|
75
|
+
it :exists do
|
76
|
+
expect(@b.has_any_value('test.plural.case3')).to eq true
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "ru-RU locale" do
|
83
|
+
before :all do
|
84
|
+
@b.locale = 'ru-RU'
|
85
|
+
end
|
86
|
+
|
87
|
+
describe :t do
|
88
|
+
it "should return placeholder if has no key" do
|
89
|
+
expect( @b.t("wow") ).to eq "[wow]"
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "test.simple.plural.nails2" do
|
93
|
+
it "for 1" do
|
94
|
+
expect(@b.t('test.simple.plural.nails2', 1)).to eq 'У меня гвоздь упрощенная форма записи'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "test.simple.plural.nails3" do
|
99
|
+
it "for 17" do
|
100
|
+
expect(@b.t('test.simple.plural.nails3', { test: 17 })).to eq '17 у меня гвоздей'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|