air18n 0.1.18 → 0.1.19
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/air18n/phrase_translation.rb +4 -4
- data/lib/air18n/smart_count.rb +40 -26
- data/lib/air18n/version.rb +1 -1
- data/spec/lib/air18n/air18n_spec.rb +36 -2
- data/spec/lib/air18n/backend_spec.rb +7 -3
- data/spec/lib/air18n/phrase_translation_spec.rb +8 -8
- data/spec/lib/air18n/smart_count_spec.rb +41 -16
- data/spec/lib/air18n/xss_detector_spec.rb +9 -9
- metadata +1 -1
@@ -299,7 +299,7 @@ module Air18n
|
|
299
299
|
end
|
300
300
|
|
301
301
|
def check_plural_forms
|
302
|
-
result = SmartCount::valid?(self.value, self.locale)
|
302
|
+
result = SmartCount::valid?(self.phrase.value, self.value, I18n.default_locale, self.locale)
|
303
303
|
if !result[:valid]
|
304
304
|
self.errors.add(:value, result[:reason])
|
305
305
|
end
|
@@ -310,7 +310,7 @@ module Air18n
|
|
310
310
|
max_length = $1.to_i
|
311
311
|
length = value.size
|
312
312
|
if length > max_length
|
313
|
-
self.errors.add(:value, "Translation has #{length} characters
|
313
|
+
self.errors.add(:value, "Translation has #{length} characters, maximum length is #{max_length} characters.")
|
314
314
|
end
|
315
315
|
end
|
316
316
|
end
|
@@ -322,8 +322,8 @@ module Air18n
|
|
322
322
|
if SmartCount::applies?(self.phrase.value) || SmartCount::applies?(self.value)
|
323
323
|
our_variables = SmartCount::dedupe_things_like_tags_or_variables(
|
324
324
|
self.locale, our_variables)
|
325
|
-
|
326
|
-
|
325
|
+
their_variables = SmartCount::dedupe_things_like_tags_or_variables(
|
326
|
+
I18n.default_locale, their_variables)
|
327
327
|
end
|
328
328
|
|
329
329
|
LoggingHelper.info "our variables: #{our_variables.inspect}"
|
data/lib/air18n/smart_count.rb
CHANGED
@@ -1,17 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Air18n
|
2
4
|
module SmartCount
|
3
5
|
# Class for choosing the right plural form of a phrase based on an
|
4
6
|
# interpolation variable with special name "smart_count" (set below in
|
5
7
|
# OPTION_NAME constant).
|
6
8
|
#
|
7
|
-
# If a phrase
|
8
|
-
#
|
9
|
+
# If a phrase's default text contains '||||', translators can specify
|
10
|
+
# multiple translations, one per possible pluralization form of the
|
9
11
|
# language. If there is more than one pluralization form, translations are
|
10
|
-
# separated by "
|
12
|
+
# separated by "||||" (set below in DELIMITER constant). The default text
|
13
|
+
# specifies all the forms for the default locale. (If the default locale is
|
14
|
+
# a single-form locale like Japanese, the default text can look like
|
15
|
+
# "%{smart_count} レビュー||||" where it ends with '||||'.
|
11
16
|
|
17
|
+
# Option to translate() that holds number which controls which plural form
|
18
|
+
# is used.
|
12
19
|
INTERPOLATION_VARIABLE_NAME = :smart_count
|
13
|
-
|
14
|
-
|
20
|
+
|
21
|
+
# Delimiter between forms of translation.
|
22
|
+
#
|
23
|
+
# This delimiter must be unique and rare because we assume that any phrase
|
24
|
+
# that includes it uses smart counting.
|
25
|
+
DELIMITER = '||||'
|
15
26
|
|
16
27
|
# C.F.
|
17
28
|
# https://developer.mozilla.org/en-US/docs/Localization_and_Plurals
|
@@ -74,29 +85,30 @@ module Air18n
|
|
74
85
|
# 'locale'.
|
75
86
|
#
|
76
87
|
# Examples:
|
77
|
-
# choose("%{smart_count} bewertung
|
88
|
+
# choose("%{smart_count} bewertung |||| %{smart_count} bewertungen",
|
78
89
|
# :de, 0)
|
79
|
-
# => %{smart_count} bewertungen
|
80
|
-
# choose("%{smart_count} bewertung
|
90
|
+
# => "%{smart_count} bewertungen"
|
91
|
+
# choose("%{smart_count} bewertung |||| %{smart_count} bewertungen",
|
81
92
|
# :de, 1)
|
82
|
-
# => %{smart_count} bewertung
|
83
|
-
# choose("%{smart_count} bewertung
|
93
|
+
# => "%{smart_count} bewertung"
|
94
|
+
# choose("%{smart_count} bewertung |||| %{smart_count} bewertungen",
|
84
95
|
# :de, 2)
|
85
|
-
# => %{smart_count} bewertungen
|
96
|
+
# => "%{smart_count} bewertungen"
|
97
|
+
# choose("%{smart_count} bewertung |||| %{smart_count} bewertungen",
|
98
|
+
# :de, nil)
|
99
|
+
# => "%{smart_count} bewertung |||| %{smart_count} bewertungen"
|
86
100
|
#
|
87
101
|
# If 'count' is nil or 'text' contains too few alternative versions, this
|
88
102
|
# method degrades gracefully by returning the first version of text.
|
89
103
|
#
|
90
104
|
# Returns if nil if text is blank.
|
91
105
|
def choose(text, locale, count)
|
92
|
-
|
93
|
-
|
94
|
-
texts = text.split(DELIMITER)
|
95
|
-
if count
|
106
|
+
if count.present? && text.present?
|
107
|
+
texts = text.split(DELIMITER)
|
96
108
|
chosen_text = texts[plural_type_index(locale, count)] || texts.first
|
97
109
|
chosen_text.strip
|
98
110
|
else
|
99
|
-
|
111
|
+
text
|
100
112
|
end
|
101
113
|
end
|
102
114
|
|
@@ -109,19 +121,21 @@ module Air18n
|
|
109
121
|
PLURAL_TYPES[plural_type_name(locale)][:rule].call(count)
|
110
122
|
end
|
111
123
|
|
112
|
-
|
113
|
-
|
114
|
-
|
124
|
+
# Returns a hint for translators translating source_text to target_locale,
|
125
|
+
# or nil if there is no smart-count-related hint.
|
126
|
+
def hint(source_text, target_locale)
|
127
|
+
if applies?(source_text)
|
128
|
+
doc_array = PLURAL_TYPES[plural_type_name(target_locale)][:doc]
|
115
129
|
if doc_array
|
116
|
-
doc_string = doc_array.join(DELIMITER + ' ')
|
117
|
-
n = num_forms(
|
130
|
+
doc_string = doc_array.join(' ' + DELIMITER + ' ')
|
131
|
+
n = num_forms(target_locale)
|
118
132
|
"Must specify #{n} forms separated by \"#{DELIMITER}\": \"#{doc_string}\""
|
119
133
|
end
|
120
134
|
end
|
121
135
|
end
|
122
136
|
|
123
137
|
def applies?(text)
|
124
|
-
!!text.index(
|
138
|
+
!!text.index(DELIMITER)
|
125
139
|
end
|
126
140
|
|
127
141
|
def num_forms(locale)
|
@@ -161,10 +175,10 @@ module Air18n
|
|
161
175
|
end
|
162
176
|
end
|
163
177
|
|
164
|
-
def valid?(
|
165
|
-
if applies?(
|
166
|
-
size =
|
167
|
-
num_forms = num_forms(
|
178
|
+
def valid?(source_text, target_text, source_locale, target_locale)
|
179
|
+
if applies?(source_text) || applies?(target_text)
|
180
|
+
size = target_text.split(DELIMITER).size
|
181
|
+
num_forms = num_forms(target_locale)
|
168
182
|
if size == num_forms
|
169
183
|
{ :valid => true }
|
170
184
|
else
|
data/lib/air18n/version.rb
CHANGED
@@ -105,6 +105,40 @@ describe Air18n do
|
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
|
+
context 'smart_count' do
|
109
|
+
it 'should work in English' do
|
110
|
+
I18n.t('smart count test',
|
111
|
+
:default => 'review |||| reviews'
|
112
|
+
).should == 'review |||| reviews'
|
113
|
+
I18n.t('smart count test',
|
114
|
+
:default => 'review |||| reviews',
|
115
|
+
:smart_count => 1
|
116
|
+
).should == 'review'
|
117
|
+
I18n.t('smart count test',
|
118
|
+
:default => 'review |||| reviews',
|
119
|
+
:smart_count => 2
|
120
|
+
).should == 'reviews'
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should work in English with other interpolation' do
|
124
|
+
I18n.t('smart count test with interpolation',
|
125
|
+
:default => 'review in %{location} |||| reviews in %{location}',
|
126
|
+
:smart_count => 2,
|
127
|
+
:location => 'Finland'
|
128
|
+
).should == 'reviews in Finland'
|
129
|
+
|
130
|
+
# You can't use smart_count without specifying all other interpolation
|
131
|
+
# variables. Otherwise you get a I18n::MissingInterpolationArgument
|
132
|
+
# error.
|
133
|
+
lambda {
|
134
|
+
I18n.t('smart count test with interpolation',
|
135
|
+
:default => 'review in %{location} |||| reviews in %{location}',
|
136
|
+
:smart_count => 2
|
137
|
+
)
|
138
|
+
}.should raise_error
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
108
142
|
context 'pluralize' do
|
109
143
|
it 'should work in English' do
|
110
144
|
I18n.pluralize(0, 'Review').should == '0 Reviews'
|
@@ -118,7 +152,7 @@ describe Air18n do
|
|
118
152
|
end
|
119
153
|
|
120
154
|
it 'should work in French' do
|
121
|
-
I18n.backend.store_translations(:fr, { 'shared.pluralize.Review' => '%{smart_count} Commentaire
|
155
|
+
I18n.backend.store_translations(:fr, { 'shared.pluralize.Review' => '%{smart_count} Commentaire |||| %{smart_count} Commentaires' })
|
122
156
|
old_locale = I18n.full_locale
|
123
157
|
I18n.full_locale = :fr
|
124
158
|
I18n.pluralize(0, 'Review').should == '0 Commentaire'
|
@@ -129,7 +163,7 @@ describe Air18n do
|
|
129
163
|
end
|
130
164
|
|
131
165
|
it 'should work with explicitly-specified plural' do
|
132
|
-
I18n.backend.store_translations(:fr, { 'shared.pluralize.feis' => '%{smart_count} french singular
|
166
|
+
I18n.backend.store_translations(:fr, { 'shared.pluralize.feis' => '%{smart_count} french singular |||| %{smart_count} french plural' })
|
133
167
|
|
134
168
|
I18n.pluralize(0, 'feis', 'feiseanna').should == '0 feiseanna'
|
135
169
|
I18n.pluralize(1, 'feis', 'feiseanna').should == '1 feis'
|
@@ -153,21 +153,25 @@ describe Air18n::Backend do
|
|
153
153
|
backend = Air18n::Backend.new
|
154
154
|
backend.lookup(
|
155
155
|
:en, 'smart count reviews', @scope,
|
156
|
-
:default => "%{smart_count} review
|
156
|
+
:default => "%{smart_count} review |||| %{smart_count} reviews",
|
157
157
|
:smart_count => 1
|
158
158
|
).should == '%{smart_count} review'
|
159
159
|
backend.lookup(
|
160
160
|
:en, 'smart count reviews', @scope,
|
161
|
-
:default => "%{smart_count} review
|
161
|
+
:default => "%{smart_count} review |||| %{smart_count} reviews",
|
162
162
|
:smart_count => 3
|
163
163
|
).should == '%{smart_count} reviews'
|
164
|
+
backend.lookup(
|
165
|
+
:en, 'smart count reviews', @scope,
|
166
|
+
:default => "%{smart_count} review |||| %{smart_count} reviews",
|
167
|
+
).should == '%{smart_count} review |||| %{smart_count} reviews'
|
164
168
|
|
165
169
|
# If a phrase is untranslated in Chinese, this can turn into "3 review"
|
166
170
|
# on the Chinese site if we are not careful and use the Chinese plural
|
167
171
|
# rules for this English fallback. This test catches this bug.
|
168
172
|
backend.lookup(
|
169
173
|
:zh, 'smart count reviews', @scope,
|
170
|
-
:default => "%{smart_count} review
|
174
|
+
:default => "%{smart_count} review |||| %{smart_count} reviews",
|
171
175
|
:smart_count => 3
|
172
176
|
).should == '%{smart_count} reviews'
|
173
177
|
end
|
@@ -41,7 +41,7 @@ describe Air18n::PhraseTranslation do
|
|
41
41
|
translation.value = 'too looooong'
|
42
42
|
translation.save.should be_false
|
43
43
|
translation.errors.should include :value
|
44
|
-
translation.errors[:value].should include "Translation has 12 characters
|
44
|
+
translation.errors[:value].should include "Translation has 12 characters, maximum length is 10 characters."
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'Should check variables' do
|
@@ -57,7 +57,7 @@ describe Air18n::PhraseTranslation do
|
|
57
57
|
|
58
58
|
context 'smart_count' do
|
59
59
|
before :all do
|
60
|
-
@phrase = FactoryGirl.create(:phrase, :key => 'variables with smart count reviews', :value => "%{smart_count} review in %{location}
|
60
|
+
@phrase = FactoryGirl.create(:phrase, :key => 'variables with smart count reviews', :value => "%{smart_count} review in %{location} |||| %{smart_count} reviews in %{location}")
|
61
61
|
end
|
62
62
|
|
63
63
|
it 'Should check variables with smart count in language with one plural form' do
|
@@ -81,10 +81,10 @@ describe Air18n::PhraseTranslation do
|
|
81
81
|
:phrase => @phrase,
|
82
82
|
:locale => :fr,
|
83
83
|
:key => 'variables with smart count reviews',
|
84
|
-
:value => 'a %{location} %{smart_count} commentaire
|
84
|
+
:value => 'a %{location} %{smart_count} commentaire |||| a %{location} %{smart_count} commentaires')
|
85
85
|
validated = translation.save
|
86
86
|
validated.should == true
|
87
|
-
translation.value = 'a %{location} %{smart_count} commentaire
|
87
|
+
translation.value = 'a %{location} %{smart_count} commentaire |||| a %{location} %{smart_countz} commentaires'
|
88
88
|
translation.save.should be_false
|
89
89
|
translation.errors.should include :value
|
90
90
|
translation.errors[:value].should include "Var %{smart_count} missing from translation"
|
@@ -96,10 +96,10 @@ describe Air18n::PhraseTranslation do
|
|
96
96
|
:phrase => @phrase,
|
97
97
|
:locale => :pl,
|
98
98
|
:key => 'variables with smart count reviews',
|
99
|
-
:value => 'a %{location} %{smart_count} ends-in-one-except-eleven
|
99
|
+
:value => 'a %{location} %{smart_count} ends-in-one-except-eleven |||| a %{location} %{smart_count} ends-in-two-through-four-except-twelve-through-fourteen |||| a %{location} %{smart_count} everything-else')
|
100
100
|
validated = translation.save
|
101
101
|
validated.should == true
|
102
|
-
translation.value = 'a %{location} %{smart_count} ends-in-one-except-eleven
|
102
|
+
translation.value = 'a %{location} %{smart_count} ends-in-one-except-eleven |||| a %{location} %{smart_count} ends-in-two-through-four-except-twelve-through-fourteen |||| a %{smart_count} everything-else'
|
103
103
|
|
104
104
|
translation.save.should be_false
|
105
105
|
translation.errors.should include :value
|
@@ -112,13 +112,13 @@ describe Air18n::PhraseTranslation do
|
|
112
112
|
:phrase => @phrase,
|
113
113
|
:locale => :de,
|
114
114
|
:key => 'variables with smart count reviews',
|
115
|
-
:value => 'a %{location} %{smart_count} bewertung
|
115
|
+
:value => 'a %{location} %{smart_count} bewertung |||| a %{location} %{smart_count} bewertungen')
|
116
116
|
validated = translation.save
|
117
117
|
validated.should == true
|
118
118
|
translation.value = 'a %{location} %{smart_count} bewertung, a %{location} %{smart_count} bewertungen'
|
119
119
|
translation.save.should be_false
|
120
120
|
translation.errors.should include :value
|
121
|
-
translation.errors[:value].should include "Must specify 2 forms separated by \"
|
121
|
+
translation.errors[:value].should include "Must specify 2 forms separated by \"||||\" (1 was specified)"
|
122
122
|
end
|
123
123
|
end
|
124
124
|
end
|
@@ -19,7 +19,7 @@ describe Air18n::SmartCount do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
it "should work in German" do
|
22
|
-
review_text = "%{smart_count} bewertung
|
22
|
+
review_text = "%{smart_count} bewertung |||| %{smart_count} bewertungen"
|
23
23
|
answers =
|
24
24
|
["%{smart_count} bewertungen"] * 1 +
|
25
25
|
["%{smart_count} bewertung"] * 1 +
|
@@ -28,7 +28,7 @@ describe Air18n::SmartCount do
|
|
28
28
|
end
|
29
29
|
|
30
30
|
it "should work in French" do
|
31
|
-
review_text = "%{smart_count} commentaire
|
31
|
+
review_text = "%{smart_count} commentaire |||| %{smart_count} commentaires"
|
32
32
|
answers =
|
33
33
|
["%{smart_count} commentaire"] * 2 +
|
34
34
|
["%{smart_count} commentaires"] * 24
|
@@ -36,7 +36,7 @@ describe Air18n::SmartCount do
|
|
36
36
|
end
|
37
37
|
|
38
38
|
it "should work in Russian" do
|
39
|
-
review_text = "%{smart_count} ends-in-one-except-eleven
|
39
|
+
review_text = "%{smart_count} ends-in-one-except-eleven |||| %{smart_count} ends-in-two-through-four-except-twelve-through-fourteen |||| %{smart_count} everything-else"
|
40
40
|
answers =
|
41
41
|
["%{smart_count} everything-else"] * 1 +
|
42
42
|
["%{smart_count} ends-in-one-except-eleven"] * 1 +
|
@@ -49,7 +49,7 @@ describe Air18n::SmartCount do
|
|
49
49
|
end
|
50
50
|
|
51
51
|
it "should work in Czech" do
|
52
|
-
review_text = "%{smart_count} one
|
52
|
+
review_text = "%{smart_count} one |||| %{smart_count} two-through-four |||| %{smart_count} everything-else"
|
53
53
|
answers =
|
54
54
|
["%{smart_count} everything-else"] * 1 +
|
55
55
|
["%{smart_count} one"] * 1 +
|
@@ -59,7 +59,7 @@ describe Air18n::SmartCount do
|
|
59
59
|
end
|
60
60
|
|
61
61
|
it "should work in Polish" do
|
62
|
-
review_text = "%{smart_count} one
|
62
|
+
review_text = "%{smart_count} one |||| %{smart_count} ends-in-two-through-four-except-twelve-through-fourteen |||| %{smart_count} everything-else"
|
63
63
|
answers =
|
64
64
|
["%{smart_count} everything-else"] * 1 +
|
65
65
|
["%{smart_count} one"] * 1 +
|
@@ -69,13 +69,26 @@ describe Air18n::SmartCount do
|
|
69
69
|
["%{smart_count} everything-else"] * 1
|
70
70
|
test_choose(review_text, :pl, answers)
|
71
71
|
end
|
72
|
+
|
73
|
+
it "should work without %{smart_count} being in the phrase" do
|
74
|
+
review_text = "ends-in-one-except-eleven |||| ends-in-two-through-four-except-twelve-through-fourteen |||| everything-else"
|
75
|
+
answers =
|
76
|
+
["everything-else"] * 1 +
|
77
|
+
["ends-in-one-except-eleven"] * 1 +
|
78
|
+
["ends-in-two-through-four-except-twelve-through-fourteen"] * 3 +
|
79
|
+
["everything-else"] * 16 +
|
80
|
+
["ends-in-one-except-eleven"] * 1 +
|
81
|
+
["ends-in-two-through-four-except-twelve-through-fourteen"] * 3 +
|
82
|
+
["everything-else"] * 1
|
83
|
+
test_choose(review_text, :ru, answers)
|
84
|
+
end
|
72
85
|
end
|
73
86
|
|
74
87
|
describe "degenerate choose" do
|
75
88
|
it "should work if too few translated forms are given" do
|
76
89
|
# One of the three Russian forms, the "everything else" form, is missing.
|
77
90
|
# The fallback should be the first form, "ends in one except eleven".
|
78
|
-
review_text = "%{smart_count} ends-in-one-except-eleven
|
91
|
+
review_text = "%{smart_count} ends-in-one-except-eleven |||| %{smart_count} ends-in-two-through-four-except-twelve-through-fourteen"
|
79
92
|
answers =
|
80
93
|
["%{smart_count} ends-in-one-except-eleven"] * 1 +
|
81
94
|
["%{smart_count} ends-in-one-except-eleven"] * 1 +
|
@@ -88,8 +101,8 @@ describe Air18n::SmartCount do
|
|
88
101
|
end
|
89
102
|
|
90
103
|
it "should work with nil count" do
|
91
|
-
review_text = "%{smart_count} ends-in-one-except-eleven
|
92
|
-
Air18n::SmartCount::choose(review_text, :ru, nil).should == "%{smart_count} ends-in-one-except-eleven"
|
104
|
+
review_text = "%{smart_count} ends-in-one-except-eleven |||| %{smart_count} ends-in-two-through-four-except-twelve-through-fourteen"
|
105
|
+
Air18n::SmartCount::choose(review_text, :ru, nil).should == "%{smart_count} ends-in-one-except-eleven |||| %{smart_count} ends-in-two-through-four-except-twelve-through-fourteen"
|
93
106
|
end
|
94
107
|
|
95
108
|
it "should work with nil text" do
|
@@ -100,8 +113,8 @@ describe Air18n::SmartCount do
|
|
100
113
|
describe 'hint' do
|
101
114
|
it 'should work' do
|
102
115
|
Air18n::SmartCount::hint('hi there', :pl).should be_nil
|
103
|
-
Air18n::SmartCount::hint('%{smart_count} reviews', :pl).should ==
|
104
|
-
"Must specify 3 forms separated by \"
|
116
|
+
Air18n::SmartCount::hint('%{smart_count} review||||%{smart_count} reviews', :pl).should ==
|
117
|
+
"Must specify 3 forms separated by \"||||\": \"When count is 1 |||| When count ends in 2-4, excluding 12-14 (2, 3, 4, 22, ...) |||| Everything else (0, 5, 6, ...)\""
|
105
118
|
Air18n::SmartCount::hint('%{smart_count} reviews', :ja).should be_nil
|
106
119
|
end
|
107
120
|
end
|
@@ -134,13 +147,25 @@ describe Air18n::SmartCount do
|
|
134
147
|
|
135
148
|
describe "valid?" do
|
136
149
|
it 'should work' do
|
137
|
-
Air18n::SmartCount::valid?(
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
Air18n::SmartCount::valid?(
|
150
|
+
Air18n::SmartCount::valid?(
|
151
|
+
'%{smart_count} review |||| %{smart_count} reviews',
|
152
|
+
'%{smart_count} レビュー',
|
153
|
+
:en, :ja).should == { :valid => true }
|
154
|
+
Air18n::SmartCount::valid?(
|
155
|
+
'%{smart_count} review |||| %{smart_count} reviews',
|
156
|
+
'%{smart_count} commentaire |||| %{smart_count} commentaires',
|
157
|
+
:en, :fr).should == { :valid => true }
|
158
|
+
Air18n::SmartCount::valid?(
|
159
|
+
'%{smart_count} review |||| %{smart_count} reviews',
|
160
|
+
'%{smart_count} ends-in-one-except-eleven |||| %{smart_count} ends-in-two-through-four-except-twelve-through-fourteen |||| %{smart_count} everything-else',
|
161
|
+
:en, :pl).should == { :valid => true }
|
162
|
+
|
163
|
+
Air18n::SmartCount::valid?(
|
164
|
+
'%{smart_count} a |||| %{smart_count} b',
|
165
|
+
'%{smart_count} a |||| %{smart_count} b |||| %{smart_count} c',
|
166
|
+
:en, :fr).should == {
|
142
167
|
:valid => false,
|
143
|
-
:reason => "Must specify 2 forms separated by \"
|
168
|
+
:reason => "Must specify 2 forms separated by \"||||\" (3 were specified)"
|
144
169
|
}
|
145
170
|
end
|
146
171
|
end
|
@@ -45,14 +45,14 @@ describe Air18n::XssDetector do
|
|
45
45
|
|
46
46
|
it "should work with smart count with one plural form" do
|
47
47
|
Air18n::XssDetector::safe?(
|
48
|
-
"<span class='count'>%{smart_count}</span> <span class='text'>review</span
|
48
|
+
"<span class='count'>%{smart_count}</span> <span class='text'>review</span> |||| <span class='count'>%{smart_count}</span> <span class='text'>reviews</span>",
|
49
49
|
"<span class='text'>レビュー</span> <span class='count'>%{smart_count}</span>",
|
50
50
|
:en, :ja
|
51
51
|
).should == { :safe => true }
|
52
52
|
|
53
53
|
# "spank" instead of "span" in the last tag.
|
54
54
|
Air18n::XssDetector::safe?(
|
55
|
-
"<span class='count'>%{smart_count}</span> <span class='text'>review</span
|
55
|
+
"<span class='count'>%{smart_count}</span> <span class='text'>review</span> |||| <span class='count'>%{smart_count}</span> <span class='text'>reviews</span>",
|
56
56
|
"<span class='text'>レビュー</span> <span class='count'>%{smart_count}</spank>",
|
57
57
|
:en, :ja
|
58
58
|
).should == { :safe => false, :reason => "HTML tags don't match: [\"<span class='count'>\", \"</span>\", \"</span>\", \"<span class='text'>\"] vs. [\"<span class='text'>\", \"</span>\", \"<span class='count'>\", \"</spank>\"]" }
|
@@ -60,22 +60,22 @@ describe Air18n::XssDetector do
|
|
60
60
|
|
61
61
|
it "should work with smart count with two plural forms" do
|
62
62
|
Air18n::XssDetector::safe?(
|
63
|
-
"<span class='count'>%{smart_count}</span> <span class='text'>review</span
|
64
|
-
"<span class='text'>commentaire</span> <span class='count'>%{smart_count}</span
|
63
|
+
"<span class='count'>%{smart_count}</span> <span class='text'>review</span> |||| <span class='count'>%{smart_count}</span> <span class='text'>reviews</span>",
|
64
|
+
"<span class='text'>commentaire</span> <span class='count'>%{smart_count}</span> |||| <span class='text'>commentaires</span> <span class='count'>%{smart_count}</span>",
|
65
65
|
:en, :fr
|
66
66
|
).should == { :safe => true }
|
67
67
|
|
68
68
|
# Second form not styled.
|
69
69
|
Air18n::LoggingHelper.info "GRRRRR"
|
70
70
|
Air18n::XssDetector::safe?(
|
71
|
-
"<span class='count'>%{smart_count}</span> <span class='text'>review</span
|
72
|
-
"<span class='text'>commentaire</span> <span class='count'>%{smart_count}</span
|
71
|
+
"<span class='count'>%{smart_count}</span> <span class='text'>review</span> |||| <span class='count'>%{smart_count}</span> <span class='text'>reviews</span>",
|
72
|
+
"<span class='text'>commentaire</span> <span class='count'>%{smart_count}</span> |||| commentaires %{smart_count}",
|
73
73
|
:en, :fr
|
74
74
|
).should == { :safe => false, :reason => "HTML tags don't match: [\"<span class='count'>\", \"</span>\", \"</span>\", \"<span class='text'>\"] vs. [\"</span>\"]" }
|
75
75
|
|
76
76
|
# Only one form being given leads to the same error.
|
77
77
|
Air18n::XssDetector::safe?(
|
78
|
-
"<span class='count'>%{smart_count}</span> <span class='text'>review</span
|
78
|
+
"<span class='count'>%{smart_count}</span> <span class='text'>review</span> |||| <span class='count'>%{smart_count}</span> <span class='text'>reviews</span>",
|
79
79
|
"<span class='text'>commentaire</span> <span class='count'>%{smart_count}</span>",
|
80
80
|
:en, :fr
|
81
81
|
).should == { :safe => false, :reason => "HTML tags don't match: [\"<span class='count'>\", \"</span>\", \"</span>\", \"<span class='text'>\"] vs. [\"</span>\"]" }
|
@@ -83,8 +83,8 @@ describe Air18n::XssDetector do
|
|
83
83
|
|
84
84
|
it "should work with smart count with three plural forms" do
|
85
85
|
Air18n::XssDetector::safe?(
|
86
|
-
"<span class='count'>%{smart_count}</span> <span class='text'>review</span
|
87
|
-
"<span class='text'>ends-in-one-except-eleven</span> <span class='count'>%{smart_count}</span
|
86
|
+
"<span class='count'>%{smart_count}</span> <span class='text'>review</span> |||| <span class='count'>%{smart_count}</span> <span class='text'>reviews</span>",
|
87
|
+
"<span class='text'>ends-in-one-except-eleven</span> <span class='count'>%{smart_count}</span> |||| <span class='text'>ends-in-two-through-four-except-twelve-through-fourteen</span> <span class='count'>%{smart_count}</span> |||| <span class='text'>everything-else</span> <span class='count'>%{smart_count}</span>",
|
88
88
|
:en, :ru
|
89
89
|
).should == { :safe => true }
|
90
90
|
end
|