air18n 0.1.18 → 0.1.19
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/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
|