delocalize 0.4.0 → 1.0.0
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/README.markdown +83 -163
- data/lib/delocalize.rb +12 -4
- data/lib/delocalize/delocalizable_parameters.rb +15 -0
- data/lib/delocalize/parameter_delocalizing.rb +70 -0
- data/lib/delocalize/parameters.rb +25 -0
- data/lib/delocalize/parsers.rb +6 -0
- data/lib/delocalize/{localized_date_time_parser.rb → parsers/date_time.rb} +39 -31
- data/lib/delocalize/parsers/number.rb +15 -0
- data/lib/delocalize/railtie.rb +8 -8
- data/lib/delocalize/version.rb +3 -0
- data/test/date_time_parser_test.rb +56 -0
- data/test/number_parser_test.rb +30 -0
- data/test/parameters_test.rb +171 -0
- data/test/test_helper.rb +7 -41
- metadata +46 -38
- data/lib/delocalize/i18n_ext.rb +0 -36
- data/lib/delocalize/localized_numeric_parser.rb +0 -18
- data/lib/delocalize/rails_ext/action_view.rb +0 -5
- data/lib/delocalize/rails_ext/active_record.rb +0 -5
- data/lib/delocalize/rails_ext/time_zone.rb +0 -7
- data/lib/delocalize/ruby_ext.rb +0 -4
- data/lib/delocalize/ruby_ext/date.rb +0 -9
- data/lib/delocalize/ruby_ext/datetime.rb +0 -9
- data/lib/delocalize/ruby_ext/numeric.rb +0 -9
- data/lib/delocalize/ruby_ext/time.rb +0 -9
- data/test/delocalize_test.rb +0 -330
data/lib/delocalize/i18n_ext.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/module/attribute_accessors'
|
2
|
-
|
3
|
-
module I18n
|
4
|
-
mattr_accessor :enable_delocalization
|
5
|
-
I18n.enable_delocalization = true
|
6
|
-
|
7
|
-
class << self
|
8
|
-
def delocalization_enabled?
|
9
|
-
!!I18n.enable_delocalization
|
10
|
-
end
|
11
|
-
|
12
|
-
def delocalization_disabled?
|
13
|
-
!delocalization_enabled?
|
14
|
-
end
|
15
|
-
|
16
|
-
def with_delocalization_disabled(&block)
|
17
|
-
old_value = I18n.enable_delocalization
|
18
|
-
I18n.enable_delocalization = false
|
19
|
-
begin
|
20
|
-
yield
|
21
|
-
ensure
|
22
|
-
I18n.enable_delocalization = old_value
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def with_delocalization_enabled(&block)
|
27
|
-
old_value = I18n.enable_delocalization
|
28
|
-
I18n.enable_delocalization = true
|
29
|
-
begin
|
30
|
-
yield
|
31
|
-
ensure
|
32
|
-
I18n.enable_delocalization = old_value
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# TODO:
|
2
|
-
# * proper documentation (comments)
|
3
|
-
module Delocalize
|
4
|
-
class LocalizedNumericParser
|
5
|
-
class << self
|
6
|
-
# Parse numbers removing unneeded characters and replacing decimal separator
|
7
|
-
# through I18n. This will return a valid Ruby Numeric value (as String).
|
8
|
-
def parse(value)
|
9
|
-
if value.is_a?(String)
|
10
|
-
separator = I18n.t(:'number.format.separator')
|
11
|
-
delimiter = I18n.t(:'number.format.delimiter')
|
12
|
-
value = value.gsub(delimiter, '').gsub(separator, '.')
|
13
|
-
end
|
14
|
-
value
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/lib/delocalize/ruby_ext.rb
DELETED
data/test/delocalize_test.rb
DELETED
@@ -1,330 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
class DelocalizeActiveRecordTest < ActiveSupport::TestCase
|
6
|
-
def setup
|
7
|
-
Time.zone = 'Berlin' # make sure everything works as expected with TimeWithZone
|
8
|
-
Timecop.freeze(Time.zone.local(2009, 3, 1, 12, 0))
|
9
|
-
@product = Product.new
|
10
|
-
end
|
11
|
-
|
12
|
-
def teardown
|
13
|
-
Timecop.return
|
14
|
-
end
|
15
|
-
|
16
|
-
test "delocalizes localized number" do
|
17
|
-
@product.price = '1.299,99'
|
18
|
-
assert_equal 1299.99, @product.price
|
19
|
-
|
20
|
-
@product.price = '-1.299,99'
|
21
|
-
assert_equal -1299.99, @product.price
|
22
|
-
end
|
23
|
-
|
24
|
-
test "delocalizes localized date with year" do
|
25
|
-
date = Date.civil(2009, 10, 19)
|
26
|
-
|
27
|
-
@product.released_on = '19. Oktober 2009'
|
28
|
-
assert_equal date, @product.released_on
|
29
|
-
|
30
|
-
@product.released_on = '19.10.2009'
|
31
|
-
assert_equal date, @product.released_on
|
32
|
-
end
|
33
|
-
|
34
|
-
test "delocalizes localized date with year even if locale changes" do
|
35
|
-
date = Date.civil(2009, 10, 19)
|
36
|
-
|
37
|
-
@product.released_on = '19. Oktober 2009'
|
38
|
-
assert_equal date, @product.released_on
|
39
|
-
|
40
|
-
I18n.with_locale :tt do
|
41
|
-
@product.released_on = '10|11|2009'
|
42
|
-
date = Date.civil(2009, 11, 10)
|
43
|
-
assert_equal date, @product.released_on
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
test "delocalizes localized date without year" do
|
48
|
-
Timecop.return
|
49
|
-
date = Date.civil(Date.today.year, 10, 19)
|
50
|
-
|
51
|
-
@product.released_on = '19. Okt'
|
52
|
-
assert_equal date, @product.released_on
|
53
|
-
end
|
54
|
-
|
55
|
-
test "delocalizes localized datetime with year" do
|
56
|
-
time = Time.zone.local(2009, 3, 1, 12, 0, 0)
|
57
|
-
|
58
|
-
@product.published_at = 'Sonntag, 1. März 2009, 12:00 Uhr'
|
59
|
-
assert_equal time, @product.published_at
|
60
|
-
|
61
|
-
@product.published_at = '1. März 2009, 12:00 Uhr'
|
62
|
-
assert_equal time, @product.published_at
|
63
|
-
end
|
64
|
-
|
65
|
-
test "delocalizes with fallback locale" do
|
66
|
-
I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
|
67
|
-
I18n.fallbacks[:xx] = [:xx, :tt]
|
68
|
-
|
69
|
-
I18n.with_locale :xx do
|
70
|
-
@product.released_on = '10|11|2009'
|
71
|
-
date = Date.civil(2009, 11, 10)
|
72
|
-
assert_equal date, @product.released_on
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
test "delocalizes localized datetime without year" do
|
77
|
-
time = Time.zone.local(Date.today.year, 3, 1, 12, 0, 0)
|
78
|
-
|
79
|
-
@product.published_at = '1. März, 12:00 Uhr'
|
80
|
-
assert_equal time, @product.published_at
|
81
|
-
end
|
82
|
-
|
83
|
-
test "delocalizes localized time (DST)" do
|
84
|
-
@product.cant_think_of_a_sensible_time_field = '09:00 Uhr'
|
85
|
-
assert_equal '09:00', @product.cant_think_of_a_sensible_time_field.strftime('%H:%M')
|
86
|
-
end
|
87
|
-
|
88
|
-
test "invalid dates should be delocalized to nil" do
|
89
|
-
date = '32. Oktober 2009'
|
90
|
-
@product.released_on = date
|
91
|
-
assert_equal nil, @product.released_on
|
92
|
-
assert_equal date, @product.released_on_before_type_cast
|
93
|
-
end
|
94
|
-
|
95
|
-
test "uses default parse if format isn't found (non-DST)" do
|
96
|
-
date = Date.civil(2009, 10, 19)
|
97
|
-
|
98
|
-
@product.released_on = '2009/10/19'
|
99
|
-
assert_equal date, @product.released_on
|
100
|
-
|
101
|
-
time = Time.zone.local(2009, 3, 1, 12, 0, 0)
|
102
|
-
@product.published_at = '2009/03/01 12:00'
|
103
|
-
assert_equal time, @product.published_at
|
104
|
-
|
105
|
-
now = Time.current
|
106
|
-
time = Time.zone.local(now.year, now.month, now.day, 8, 0, 0)
|
107
|
-
@product.cant_think_of_a_sensible_time_field = '08:00'
|
108
|
-
assert_equal time, @product.cant_think_of_a_sensible_time_field
|
109
|
-
end
|
110
|
-
|
111
|
-
test "should return nil if the input is empty or invalid" do
|
112
|
-
@product.released_on = ""
|
113
|
-
assert_nil @product.released_on
|
114
|
-
|
115
|
-
@product.released_on = "aa"
|
116
|
-
assert_nil @product.released_on
|
117
|
-
end
|
118
|
-
|
119
|
-
test "doesn't raise when attribute is nil" do
|
120
|
-
assert_nothing_raised {
|
121
|
-
@product.price = nil
|
122
|
-
@product.released_on = nil
|
123
|
-
@product.published_at = nil
|
124
|
-
@product.cant_think_of_a_sensible_time_field = nil
|
125
|
-
}
|
126
|
-
end
|
127
|
-
|
128
|
-
test "uses default formats if enable_delocalization is false" do
|
129
|
-
I18n.enable_delocalization = false
|
130
|
-
|
131
|
-
@product.price = '1299.99'
|
132
|
-
assert_equal 1299.99, @product.price
|
133
|
-
|
134
|
-
@product.price = '-1299.99'
|
135
|
-
assert_equal -1299.99, @product.price
|
136
|
-
end
|
137
|
-
|
138
|
-
test "uses default formats if called with with_delocalization_disabled" do
|
139
|
-
I18n.with_delocalization_disabled do
|
140
|
-
@product.price = '1299.99'
|
141
|
-
assert_equal 1299.99, @product.price
|
142
|
-
|
143
|
-
@product.price = '-1299.99'
|
144
|
-
assert_equal -1299.99, @product.price
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
test "properly resets when an error is raised in a with_delocalization_disabled block" do
|
149
|
-
I18n.enable_delocalization = true
|
150
|
-
I18n.with_delocalization_disabled do
|
151
|
-
raise 'error'
|
152
|
-
end rescue nil
|
153
|
-
assert_equal true, I18n.enable_delocalization
|
154
|
-
end
|
155
|
-
|
156
|
-
test "uses localized parsing if called with with_delocalization_enabled" do
|
157
|
-
I18n.with_delocalization_enabled do
|
158
|
-
@product.price = '1.299,99'
|
159
|
-
assert_equal 1299.99, @product.price
|
160
|
-
|
161
|
-
@product.price = '-1.299,99'
|
162
|
-
assert_equal -1299.99, @product.price
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
test "properly resets when an error is raised in a with_delocalization_enabled block" do
|
167
|
-
I18n.enable_delocalization = false
|
168
|
-
I18n.with_delocalization_enabled do
|
169
|
-
raise 'error'
|
170
|
-
end rescue nil
|
171
|
-
assert_equal false, I18n.enable_delocalization
|
172
|
-
end
|
173
|
-
|
174
|
-
test "dirty attributes must detect changes in decimal columns" do
|
175
|
-
@product.price = 10
|
176
|
-
@product.save
|
177
|
-
@product.price = "10,34"
|
178
|
-
assert @product.price_changed?
|
179
|
-
end
|
180
|
-
|
181
|
-
test "dirty attributes must detect changes in float columns" do
|
182
|
-
@product.weight = 10
|
183
|
-
@product.save
|
184
|
-
@product.weight = "10,34"
|
185
|
-
assert @product.weight_changed?
|
186
|
-
end
|
187
|
-
|
188
|
-
test "attributes that didn't change shouldn't be marked dirty" do
|
189
|
-
@product.name = "Good cookies, Really good"
|
190
|
-
@product.save
|
191
|
-
@product.name = "Good cookies, Really good"
|
192
|
-
assert !@product.name_changed?
|
193
|
-
end
|
194
|
-
|
195
|
-
test "should remember the value before type cast" do
|
196
|
-
@product.price = "asd"
|
197
|
-
assert_equal @product.price, 0
|
198
|
-
assert_equal @product.price_before_type_cast, "asd"
|
199
|
-
end
|
200
|
-
|
201
|
-
test 'it should gsub only whole translated words and not mess up the original string' do
|
202
|
-
orig_march = I18n.t('date.month_names')[3]
|
203
|
-
orig_monday = I18n.t('date.abbr_day_names')[1]
|
204
|
-
|
205
|
-
#Simulate Dutch
|
206
|
-
I18n.t('date.month_names')[3] = 'Maart'
|
207
|
-
I18n.t('date.abbr_day_names')[1] = 'Ma'
|
208
|
-
|
209
|
-
subject = '30 Maart 2011'
|
210
|
-
Delocalize::LocalizedDateTimeParser.send(:translate_month_and_day_names, subject)
|
211
|
-
|
212
|
-
assert_equal subject, '30 March 2011'
|
213
|
-
|
214
|
-
I18n.t('date.month_names')[3] = orig_march
|
215
|
-
I18n.t('date.abbr_day_names')[1] = orig_monday
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
class DelocalizeActionViewTest < ActiveSupport::TestCase
|
220
|
-
include ActionView::Helpers::FormHelper
|
221
|
-
|
222
|
-
def setup
|
223
|
-
Time.zone = 'Berlin' # make sure everything works as expected with TimeWithZone
|
224
|
-
@product = Product.new
|
225
|
-
end
|
226
|
-
|
227
|
-
test "shows text field using formatted number" do
|
228
|
-
@product.price = 1299.9
|
229
|
-
assert_match /value="1\.299,90"/, text_field(:product, :price)
|
230
|
-
end
|
231
|
-
|
232
|
-
test "shows text field using formatted number with options" do
|
233
|
-
@product.price = 1299.995
|
234
|
-
assert_match /value="1,299\.995"/, text_field(:product, :price, :precision => 3, :delimiter => ',', :separator => '.')
|
235
|
-
end
|
236
|
-
|
237
|
-
test "shows text field using formatted number without precision if column is an integer" do
|
238
|
-
@product.times_sold = 20
|
239
|
-
assert_match /value="20"/, text_field(:product, :times_sold)
|
240
|
-
|
241
|
-
@product.times_sold = 2000
|
242
|
-
assert_match /value="2\.000"/, text_field(:product, :times_sold)
|
243
|
-
end
|
244
|
-
|
245
|
-
test "shows text field using formatted date" do
|
246
|
-
@product.released_on = Date.civil(2009, 10, 19)
|
247
|
-
assert_match /value="19\.10\.2009"/, text_field(:product, :released_on)
|
248
|
-
end
|
249
|
-
|
250
|
-
test "shows text field using formatted date and time" do
|
251
|
-
@product.published_at = Time.zone.local(2009, 3, 1, 12, 0, 0)
|
252
|
-
# careful - leading whitespace with %e
|
253
|
-
assert_match /value="Sonntag, 1\. März 2009, 12:00 Uhr"/, text_field(:product, :published_at)
|
254
|
-
end
|
255
|
-
|
256
|
-
test "shows text field using formatted date with format" do
|
257
|
-
@product.released_on = Date.civil(2009, 10, 19)
|
258
|
-
assert_match /value="19\. Oktober 2009"/, text_field(:product, :released_on, :format => :long)
|
259
|
-
end
|
260
|
-
|
261
|
-
test "shows text field using formatted date and time with format" do
|
262
|
-
@product.published_at = Time.zone.local(2009, 3, 1, 12, 0, 0)
|
263
|
-
# careful - leading whitespace with %e
|
264
|
-
assert_match /value=" 1\. März, 12:00 Uhr"/, text_field(:product, :published_at, :format => :short)
|
265
|
-
end
|
266
|
-
|
267
|
-
test "shows text field using formatted time with format" do
|
268
|
-
@product.cant_think_of_a_sensible_time_field = Time.zone.local(2009, 3, 1, 9, 0, 0)
|
269
|
-
assert_match /value="09:00 Uhr"/, text_field(:product, :cant_think_of_a_sensible_time_field, :format => :time)
|
270
|
-
end
|
271
|
-
|
272
|
-
test "integer hidden fields shouldn't be formatted" do
|
273
|
-
@product.times_sold = 1000
|
274
|
-
assert_match /value="1000"/, hidden_field(:product, :times_sold)
|
275
|
-
end
|
276
|
-
|
277
|
-
test "doesn't raise an exception when object is nil" do
|
278
|
-
assert_nothing_raised {
|
279
|
-
text_field(:not_here, :a_text_field)
|
280
|
-
}
|
281
|
-
end
|
282
|
-
|
283
|
-
test "doesn't raise for nil Date/Time" do
|
284
|
-
@product.published_at, @product.released_on, @product.cant_think_of_a_sensible_time_field = nil
|
285
|
-
assert_nothing_raised {
|
286
|
-
text_field(:product, :published_at)
|
287
|
-
text_field(:product, :released_on)
|
288
|
-
text_field(:product, :cant_think_of_a_sensible_time_field)
|
289
|
-
}
|
290
|
-
end
|
291
|
-
|
292
|
-
test "delocalizes a given non-string :value" do
|
293
|
-
@product.price = 1299.9
|
294
|
-
assert_match /value="1\.499,90"/, text_field(:product, :price, :value => 1499.90)
|
295
|
-
end
|
296
|
-
|
297
|
-
test "doesn't override given string :value" do
|
298
|
-
@product.price = 1299.9
|
299
|
-
assert_match /value="1\.499,90"/, text_field(:product, :price, :value => "1.499,90")
|
300
|
-
end
|
301
|
-
|
302
|
-
test "doesn't convert the value if field has numericality errors" do
|
303
|
-
@product = ProductWithValidation.new(:price => 'this is not a number')
|
304
|
-
@product.valid?
|
305
|
-
assert_match /value="this is not a number"/, text_field(:product, :price)
|
306
|
-
end
|
307
|
-
|
308
|
-
test "should convert the value if field have non-numericality errors, but have other errors, e.g. business rules" do
|
309
|
-
@product = ProductWithBusinessValidation.new(:price => '1.337,66')
|
310
|
-
@product.valid?
|
311
|
-
assert_match /value="1\.337,66"/, text_field(:product, :price)
|
312
|
-
end
|
313
|
-
|
314
|
-
test "doesn't raise an exception when object isn't an ActiveReccord" do
|
315
|
-
@product = NonArProduct.new
|
316
|
-
assert_nothing_raised {
|
317
|
-
text_field(:product, :name)
|
318
|
-
text_field(:product, :times_sold)
|
319
|
-
text_field(:product, :published_at)
|
320
|
-
text_field(:product, :released_on)
|
321
|
-
text_field(:product, :cant_think_of_a_sensible_time_field)
|
322
|
-
text_field(:product, :price, :value => "1.499,90")
|
323
|
-
}
|
324
|
-
end
|
325
|
-
|
326
|
-
test "formats field with default value correctly" do
|
327
|
-
assert_match /value="0,00"/, text_field(:product, :some_value_with_default)
|
328
|
-
end
|
329
|
-
end
|
330
|
-
|