1# -*- coding: utf-8 -*-
2import datetime
3import gettext as gettext_stdlib
4import os
5
6from babel.numbers import NumberFormatError
7
8from pytz.gae import pytz
9
10import webapp2
11from webapp2_extras import i18n
12
13import test_base
14
15class I18nTestCase(test_base.BaseTestCase):
16
17    def setUp(self):
18        super(I18nTestCase, self).setUp()
19
20        app = webapp2.WSGIApplication()
21        request = webapp2.Request.blank('/')
22        request.app = app
23
24        app.set_globals(app=app, request=request)
25
26        self.app = app
27        self.request = request
28
29    #==========================================================================
30    # _(), gettext(), ngettext(), lazy_gettext(), lazy_ngettext()
31    #==========================================================================
32
33    def test_translations_not_set(self):
34        # We release it here because it is set on setUp()
35        self.app.clear_globals()
36        self.assertRaises(AssertionError, i18n.gettext, 'foo')
37
38    def test_gettext(self):
39        self.assertEqual(i18n.gettext('foo'), u'foo')
40
41    def test_gettext_(self):
42        self.assertEqual(i18n._('foo'), u'foo')
43
44    def test_gettext_with_variables(self):
45        self.assertEqual(i18n.gettext('foo %(foo)s'), u'foo %(foo)s')
46        self.assertEqual(i18n.gettext('foo %(foo)s') % {'foo': 'bar'}, u'foo bar')
47        self.assertEqual(i18n.gettext('foo %(foo)s', foo='bar'), u'foo bar')
48
49    def test_ngettext(self):
50        self.assertEqual(i18n.ngettext('One foo', 'Many foos', 1), u'One foo')
51        self.assertEqual(i18n.ngettext('One foo', 'Many foos', 2), u'Many foos')
52
53    def test_ngettext_with_variables(self):
54        self.assertEqual(i18n.ngettext('One foo %(foo)s', 'Many foos %(foo)s', 1), u'One foo %(foo)s')
55        self.assertEqual(i18n.ngettext('One foo %(foo)s', 'Many foos %(foo)s', 2), u'Many foos %(foo)s')
56        self.assertEqual(i18n.ngettext('One foo %(foo)s', 'Many foos %(foo)s', 1, foo='bar'), u'One foo bar')
57        self.assertEqual(i18n.ngettext('One foo %(foo)s', 'Many foos %(foo)s', 2, foo='bar'), u'Many foos bar')
58        self.assertEqual(i18n.ngettext('One foo %(foo)s', 'Many foos %(foo)s', 1) % {'foo': 'bar'}, u'One foo bar')
59        self.assertEqual(i18n.ngettext('One foo %(foo)s', 'Many foos %(foo)s', 2) % {'foo': 'bar'}, u'Many foos bar')
60
61    def test_lazy_gettext(self):
62        self.assertEqual(i18n.lazy_gettext('foo'), u'foo')
63
64    #==========================================================================
65    # Date formatting
66    #==========================================================================
67
68    def test_format_date(self):
69        value = datetime.datetime(2009, 11, 10, 16, 36, 05)
70
71        self.assertEqual(i18n.format_date(value, format='short'), u'11/10/09')
72        self.assertEqual(i18n.format_date(value, format='medium'), u'Nov 10, 2009')
73        self.assertEqual(i18n.format_date(value, format='long'), u'November 10, 2009')
74        self.assertEqual(i18n.format_date(value, format='full'), u'Tuesday, November 10, 2009')
75
76    def test_format_date_no_format(self):
77        value = datetime.datetime(2009, 11, 10, 16, 36, 05)
78        self.assertEqual(i18n.format_date(value), u'Nov 10, 2009')
79
80    '''
81    def test_format_date_no_format_but_configured(self):
82        app = App(config={
83            'tipfy.sessions': {
84                'secret_key': 'secret',
85            },
86            'tipfy.i18n': {
87                'timezone': 'UTC',
88                'date_formats': {
89                    'time':             'medium',
90                    'date':             'medium',
91                    'datetime':         'medium',
92                    'time.short':       None,
93                    'time.medium':      None,
94                    'time.full':        None,
95                    'time.long':        None,
96                    'date.short':       None,
97                    'date.medium':      'full',
98                    'date.full':        None,
99                    'date.long':        None,
100                    'datetime.short':   None,
101                    'datetime.medium':  None,
102                    'datetime.full':    None,
103                    'datetime.long':    None,
104                }
105            }
106        })
107        local.request = request = Request.from_values('/')
108        request.app = app
109
110        value = datetime.datetime(2009, 11, 10, 16, 36, 05)
111        self.assertEqual(i18n.format_date(value), u'Tuesday, November 10, 2009')
112    '''
113
114    def test_format_date_pt_BR(self):
115        i18n.get_i18n().set_locale('pt_BR')
116        value = datetime.datetime(2009, 11, 10, 16, 36, 05)
117
118        self.assertEqual(i18n.format_date(value, format='short'), u'10/11/09')
119        self.assertEqual(i18n.format_date(value, format='medium'), u'10/11/2009')
120        self.assertEqual(i18n.format_date(value, format='long'), u'10 de novembro de 2009')
121        self.assertEqual(i18n.format_date(value, format='full'), u'terça-feira, 10 de novembro de 2009')
122
123    def test_format_datetime(self):
124        value = datetime.datetime(2009, 11, 10, 16, 36, 05)
125
126        self.assertEqual(i18n.format_datetime(value, format='short'), u'11/10/09 4:36 PM')
127        self.assertEqual(i18n.format_datetime(value, format='medium'), u'Nov 10, 2009 4:36:05 PM')
128        self.assertEqual(i18n.format_datetime(value, format='long'), u'November 10, 2009 4:36:05 PM +0000')
129        #self.assertEqual(i18n.format_datetime(value, format='full'), u'Tuesday, November 10, 2009 4:36:05 PM World (GMT) Time')
130        self.assertEqual(i18n.format_datetime(value, format='full'), u'Tuesday, November 10, 2009 4:36:05 PM GMT+00:00')
131
132        i18n.get_i18n().set_timezone('America/Chicago')
133        self.assertEqual(i18n.format_datetime(value, format='short'), u'11/10/09 10:36 AM')
134
135    def test_format_datetime_no_format(self):
136        value = datetime.datetime(2009, 11, 10, 16, 36, 05)
137        self.assertEqual(i18n.format_datetime(value), u'Nov 10, 2009 4:36:05 PM')
138
139    def test_format_datetime_pt_BR(self):
140        i18n.get_i18n().set_locale('pt_BR')
141        value = datetime.datetime(2009, 11, 10, 16, 36, 05)
142
143        self.assertEqual(i18n.format_datetime(value, format='short'), u'10/11/09 16:36')
144        self.assertEqual(i18n.format_datetime(value, format='medium'), u'10/11/2009 16:36:05')
145        #self.assertEqual(i18n.format_datetime(value, format='long'), u'10 de novembro de 2009 16:36:05 +0000')
146        self.assertEqual(i18n.format_datetime(value, format='long'), u'10 de novembro de 2009 16h36min05s +0000')
147        #self.assertEqual(i18n.format_datetime(value, format='full'), u'terça-feira, 10 de novembro de 2009 16h36min05s Horário Mundo (GMT)')
148        self.assertEqual(i18n.format_datetime(value, format='full'), u'ter\xe7a-feira, 10 de novembro de 2009 16h36min05s GMT+00:00')
149
150    def test_format_time(self):
151        value = datetime.datetime(2009, 11, 10, 16, 36, 05)
152
153        self.assertEqual(i18n.format_time(value, format='short'), u'4:36 PM')
154        self.assertEqual(i18n.format_time(value, format='medium'), u'4:36:05 PM')
155        self.assertEqual(i18n.format_time(value, format='long'), u'4:36:05 PM +0000')
156        #self.assertEqual(i18n.format_time(value, format='full'), u'4:36:05 PM World (GMT) Time')
157        self.assertEqual(i18n.format_time(value, format='full'), u'4:36:05 PM GMT+00:00')
158
159    def test_format_time_no_format(self):
160        value = datetime.datetime(2009, 11, 10, 16, 36, 05)
161        self.assertEqual(i18n.format_time(value), u'4:36:05 PM')
162
163    def test_format_time_pt_BR(self):
164        i18n.get_i18n().set_locale('pt_BR')
165        value = datetime.datetime(2009, 11, 10, 16, 36, 05)
166
167        self.assertEqual(i18n.format_time(value, format='short'), u'16:36')
168        self.assertEqual(i18n.format_time(value, format='medium'), u'16:36:05')
169        #self.assertEqual(i18n.format_time(value, format='long'), u'16:36:05 +0000')
170        self.assertEqual(i18n.format_time(value, format='long'), u'16h36min05s +0000')
171        #self.assertEqual(i18n.format_time(value, format='full'), u'16h36min05s Horário Mundo (GMT)')
172        self.assertEqual(i18n.format_time(value, format='full'), u'16h36min05s GMT+00:00')
173
174        i18n.get_i18n().set_timezone('America/Chicago')
175        self.assertEqual(i18n.format_time(value, format='short'), u'10:36')
176
177    def test_parse_date(self):
178        i18n.get_i18n().set_locale('en_US')
179        self.assertEqual(i18n.parse_date('4/1/04'), datetime.date(2004, 4, 1))
180        i18n.get_i18n().set_locale('de_DE')
181        self.assertEqual(i18n.parse_date('01.04.2004'), datetime.date(2004, 4, 1))
182
183    def test_parse_datetime(self):
184        i18n.get_i18n().set_locale('en_US')
185        self.assertRaises(NotImplementedError, i18n.parse_datetime, '4/1/04 16:08:09')
186
187    def test_parse_time(self):
188        i18n.get_i18n().set_locale('en_US')
189        self.assertEqual(i18n.parse_time('18:08:09'), datetime.time(18, 8, 9))
190        i18n.get_i18n().set_locale('de_DE')
191        self.assertEqual(i18n.parse_time('18:08:09'), datetime.time(18, 8, 9))
192
193    def test_format_timedelta(self):
194        # This is only present in Babel dev, so skip if not available.
195        if not getattr(i18n, 'format_timedelta', None):
196            return
197
198        i18n.get_i18n().set_locale('en_US')
199        # ???
200        # self.assertEqual(i18n.format_timedelta(datetime.timedelta(weeks=12)), u'3 months')
201        self.assertEqual(i18n.format_timedelta(datetime.timedelta(weeks=12)), u'3 mths')
202        i18n.get_i18n().set_locale('es')
203        # self.assertEqual(i18n.format_timedelta(datetime.timedelta(seconds=1)), u'1 segundo')
204        self.assertEqual(i18n.format_timedelta(datetime.timedelta(seconds=1)), u'1 s')
205        i18n.get_i18n().set_locale('en_US')
206        self.assertEqual(i18n.format_timedelta(datetime.timedelta(hours=3), granularity='day'), u'1 day')
207        self.assertEqual(i18n.format_timedelta(datetime.timedelta(hours=23), threshold=0.9), u'1 day')
208        # self.assertEqual(i18n.format_timedelta(datetime.timedelta(hours=23), threshold=1.1), u'23 hours')
209        self.assertEqual(i18n.format_timedelta(datetime.timedelta(hours=23), threshold=1.1), u'23 hrs')
210        self.assertEqual(i18n.format_timedelta(datetime.datetime.now() - datetime.timedelta(days=5)), u'5 days')
211
212    def test_format_iso(self):
213        value = datetime.datetime(2009, 11, 10, 16, 36, 05)
214
215        self.assertEqual(i18n.format_date(value, format='iso'), u'2009-11-10')
216        self.assertEqual(i18n.format_time(value, format='iso'), u'16:36:05')
217        self.assertEqual(i18n.format_datetime(value, format='iso'), u'2009-11-10T16:36:05+0000')
218
219    #==========================================================================
220    # Timezones
221    #==========================================================================
222
223    def test_set_timezone(self):
224        i18n.get_i18n().set_timezone('UTC')
225        self.assertEqual(i18n.get_i18n().tzinfo.zone, 'UTC')
226
227        i18n.get_i18n().set_timezone('America/Chicago')
228        self.assertEqual(i18n.get_i18n().tzinfo.zone, 'America/Chicago')
229
230        i18n.get_i18n().set_timezone('America/Sao_Paulo')
231        self.assertEqual(i18n.get_i18n().tzinfo.zone, 'America/Sao_Paulo')
232
233    def test_to_local_timezone(self):
234        i18n.get_i18n().set_timezone('US/Eastern')
235
236        format = '%Y-%m-%d %H:%M:%S %Z%z'
237
238        # Test datetime with timezone set
239        base = datetime.datetime(2002, 10, 27, 6, 0, 0, tzinfo=pytz.UTC)
240        localtime = i18n.to_local_timezone(base)
241        result = localtime.strftime(format)
242        self.assertEqual(result, '2002-10-27 01:00:00 EST-0500')
243
244        # Test naive datetime - no timezone set
245        base = datetime.datetime(2002, 10, 27, 6, 0, 0)
246        localtime = i18n.to_local_timezone(base)
247        result = localtime.strftime(format)
248        self.assertEqual(result, '2002-10-27 01:00:00 EST-0500')
249
250    def test_to_utc(self):
251        i18n.get_i18n().set_timezone('US/Eastern')
252
253        format = '%Y-%m-%d %H:%M:%S'
254
255        # Test datetime with timezone set
256        base = datetime.datetime(2002, 10, 27, 6, 0, 0, tzinfo=pytz.UTC)
257        localtime = i18n.to_utc(base)
258        result = localtime.strftime(format)
259
260        self.assertEqual(result, '2002-10-27 06:00:00')
261
262        # Test naive datetime - no timezone set
263        base = datetime.datetime(2002, 10, 27, 6, 0, 0)
264        localtime = i18n.to_utc(base)
265        result = localtime.strftime(format)
266        self.assertEqual(result, '2002-10-27 11:00:00')
267
268    def test_get_timezone_location(self):
269        i18n.get_i18n().set_locale('de_DE')
270        self.assertEqual(i18n.get_timezone_location(pytz.timezone('America/St_Johns')), u'Kanada (St. John\'s)')
271        i18n.get_i18n().set_locale('de_DE')
272        self.assertEqual(i18n.get_timezone_location(pytz.timezone('America/Mexico_City')), u'Mexiko (Mexiko-Stadt)')
273        i18n.get_i18n().set_locale('de_DE')
274        self.assertEqual(i18n.get_timezone_location(pytz.timezone('Europe/Berlin')), u'Deutschland')
275
276    #==========================================================================
277    # Number formatting
278    #==========================================================================
279
280    def test_format_number(self):
281        i18n.get_i18n().set_locale('en_US')
282        self.assertEqual(i18n.format_number(1099), u'1,099')
283
284    def test_format_decimal(self):
285        i18n.get_i18n().set_locale('en_US')
286        self.assertEqual(i18n.format_decimal(1.2345), u'1.234')
287        self.assertEqual(i18n.format_decimal(1.2346), u'1.235')
288        self.assertEqual(i18n.format_decimal(-1.2346), u'-1.235')
289        self.assertEqual(i18n.format_decimal(12345.5), u'12,345.5')
290
291        i18n.get_i18n().set_locale('sv_SE')
292        self.assertEqual(i18n.format_decimal(1.2345), u'1,234')
293
294        i18n.get_i18n().set_locale('de')
295        self.assertEqual(i18n.format_decimal(12345), u'12.345')
296
297    def test_format_currency(self):
298        i18n.get_i18n().set_locale('en_US')
299        self.assertEqual(i18n.format_currency(1099.98, 'USD'), u'$1,099.98')
300        self.assertEqual(i18n.format_currency(1099.98, 'EUR', u'\xa4\xa4 #,##0.00'), u'EUR 1,099.98')
301
302        i18n.get_i18n().set_locale('es_CO')
303        self.assertEqual(i18n.format_currency(1099.98, 'USD'), u'US$\xa01.099,98')
304
305        i18n.get_i18n().set_locale('de_DE')
306        self.assertEqual(i18n.format_currency(1099.98, 'EUR'), u'1.099,98\xa0\u20ac')
307
308    def test_format_percent(self):
309        i18n.get_i18n().set_locale('en_US')
310        self.assertEqual(i18n.format_percent(0.34), u'34%')
311        self.assertEqual(i18n.format_percent(25.1234), u'2,512%')
312        self.assertEqual(i18n.format_percent(25.1234, u'#,##0\u2030'), u'25,123\u2030')
313
314        i18n.get_i18n().set_locale('sv_SE')
315        self.assertEqual(i18n.format_percent(25.1234), u'2\xa0512\xa0%')
316
317    def test_format_scientific(self):
318        i18n.get_i18n().set_locale('en_US')
319        self.assertEqual(i18n.format_scientific(10000), u'1E4')
320        self.assertEqual(i18n.format_scientific(1234567, u'##0E00'), u'1.23E06')
321
322    def test_parse_number(self):
323        i18n.get_i18n().set_locale('en_US')
324        self.assertEqual(i18n.parse_number('1,099'), 1099L)
325
326        i18n.get_i18n().set_locale('de_DE')
327        self.assertEqual(i18n.parse_number('1.099'), 1099L)
328
329    def test_parse_number2(self):
330        i18n.get_i18n().set_locale('de')
331        self.assertRaises(NumberFormatError, i18n.parse_number, '1.099,98')
332
333    def test_parse_decimal(self):
334        i18n.get_i18n().set_locale('en_US')
335        self.assertEqual(i18n.parse_decimal('1,099.98'), 1099.98)
336
337        i18n.get_i18n().set_locale('de')
338        self.assertEqual(i18n.parse_decimal('1.099,98'), 1099.98)
339
340    def test_parse_decimal_error(self):
341        i18n.get_i18n().set_locale('de')
342        self.assertRaises(NumberFormatError, i18n.parse_decimal, '2,109,998')
343
344    def test_set_i18n_store(self):
345        app = webapp2.WSGIApplication()
346        req = webapp2.Request.blank('/')
347        req.app = app
348        store = i18n.I18nStore(app)
349
350        self.assertEqual(len(app.registry), 0)
351        i18n.set_store(store, app=app)
352        self.assertEqual(len(app.registry), 1)
353        s = i18n.get_store(app=app)
354        self.assertTrue(isinstance(s, i18n.I18nStore))
355
356    def test_get_i18n_store(self):
357        app = webapp2.WSGIApplication()
358        req = webapp2.Request.blank('/')
359        req.app = app
360        self.assertEqual(len(app.registry), 0)
361        s = i18n.get_store(app=app)
362        self.assertEqual(len(app.registry), 1)
363        self.assertTrue(isinstance(s, i18n.I18nStore))
364
365    def test_set_i18n(self):
366        app = webapp2.WSGIApplication()
367        req = webapp2.Request.blank('/')
368        req.app = app
369        store = i18n.I18n(req)
370
371        self.assertEqual(len(app.registry), 1)
372        self.assertEqual(len(req.registry), 0)
373        i18n.set_i18n(store, request=req)
374        self.assertEqual(len(app.registry), 1)
375        self.assertEqual(len(req.registry), 1)
376        i = i18n.get_i18n(request=req)
377        self.assertTrue(isinstance(i, i18n.I18n))
378
379    def test_get_i18n(self):
380        app = webapp2.WSGIApplication()
381        req = webapp2.Request.blank('/')
382        req.app = app
383        self.assertEqual(len(app.registry), 0)
384        self.assertEqual(len(req.registry), 0)
385        i = i18n.get_i18n(request=req)
386        self.assertEqual(len(app.registry), 1)
387        self.assertEqual(len(req.registry), 1)
388        self.assertTrue(isinstance(i, i18n.I18n))
389
390    def test_set_locale_selector(self):
391        i18n.get_store().set_locale_selector(
392            'resources.i18n.locale_selector')
393
394    def test_set_timezone_selector(self):
395        i18n.get_store().set_timezone_selector(
396            'resources.i18n.timezone_selector')
397
398if __name__ == '__main__':
399    test_base.main()
400