Michael Merickel
2018-10-15 3670c2cdb732d378ba6d38e72e7cd875ff726aa9
commit | author | age
7534ba 1 # -*- coding: utf-8 -*-
CM 2 #
24b1c8 3 import os
CM 4
5 here = os.path.dirname(__file__)
6 localedir = os.path.join(here, 'pkgs', 'localeapp', 'locale')
7534ba 7
CM 8 import unittest
330164 9 from pyramid import testing
7534ba 10
CM 11 class TestTranslationString(unittest.TestCase):
12     def _makeOne(self, *arg, **kw):
b60bdb 13         from pyramid.i18n import TranslationString
7534ba 14         return TranslationString(*arg, **kw)
CM 15
16     def test_it(self):
17         # this is part of the API, we don't actually need to test much more
18         # than that it's importable
19         ts = self._makeOne('a')
20         self.assertEqual(ts, 'a')
21
22 class TestTranslationStringFactory(unittest.TestCase):
23     def _makeOne(self, *arg, **kw):
b60bdb 24         from pyramid.i18n import TranslationStringFactory
7534ba 25         return TranslationStringFactory(*arg, **kw)
CM 26
27     def test_it(self):
28         # this is part of the API, we don't actually need to test much more
29         # than that it's importable
30         factory = self._makeOne('a')
31         self.assertEqual(factory('').domain, 'a')
32
33 class TestLocalizer(unittest.TestCase):
34     def _makeOne(self, *arg, **kw):
b60bdb 35         from pyramid.i18n import Localizer
7534ba 36         return Localizer(*arg, **kw)
CM 37
38     def test_ctor(self):
39         localizer = self._makeOne('en_US', None)
40         self.assertEqual(localizer.locale_name, 'en_US')
41         self.assertEqual(localizer.translations, None)
42
43     def test_translate(self):
44         translations = DummyTranslations()
45         localizer = self._makeOne(None, translations)
46         self.assertEqual(localizer.translate('123', domain='1',
47                                              mapping={}), '123')
a1d395 48         self.assertTrue(localizer.translator)
7534ba 49
CM 50     def test_pluralize(self):
51         translations = DummyTranslations()
52         localizer = self._makeOne(None, translations)
884807 53         result = localizer.pluralize('singular', 'plural', 1,
CM 54                                      domain='1', mapping={})
55         self.assertEqual(result, 'singular')
a1d395 56         self.assertTrue(localizer.pluralizer)
7534ba 57
a6e30e 58     def test_pluralize_pluralizer_already_added(self):
CM 59         translations = DummyTranslations()
60         localizer = self._makeOne(None, translations)
61         def pluralizer(*arg, **kw):
62             return arg, kw
63         localizer.pluralizer = pluralizer
64         result = localizer.pluralize('singular', 'plural', 1, domain='1',
65                                      mapping={})
66         self.assertEqual(
67             result,
68             (('singular', 'plural', 1), {'domain': '1', 'mapping': {}})
69             )
a1d395 70         self.assertTrue(localizer.pluralizer is pluralizer)
a6e30e 71
5b5cd6 72     def test_pluralize_default_translations(self):
CM 73         # test that even without message ids loaded that
74         # "localizer.pluralize" "works" instead of raising an inscrutable
75         # "translations object has no attr 'plural' error; see
76         # see https://github.com/Pylons/pyramid/issues/235
77         from pyramid.i18n import Translations
78         translations = Translations()
79         translations._catalog = {}
80         localizer = self._makeOne(None, translations)
81         result = localizer.pluralize('singular', 'plural', 2, domain='1',
82                                      mapping={})
83         self.assertEqual(result, 'plural')
84
7534ba 85 class Test_negotiate_locale_name(unittest.TestCase):
CM 86     def setUp(self):
330164 87         testing.setUp()
7534ba 88
CM 89     def tearDown(self):
330164 90         testing.tearDown()
7534ba 91
CM 92     def _callFUT(self, request):
b60bdb 93         from pyramid.i18n import negotiate_locale_name
7534ba 94         return negotiate_locale_name(request)
CM 95
96     def _registerImpl(self, impl):
b60bdb 97         from pyramid.threadlocal import get_current_registry
7534ba 98         registry = get_current_registry()
b60bdb 99         from pyramid.interfaces import ILocaleNegotiator
7534ba 100         registry.registerUtility(impl, ILocaleNegotiator)
CM 101
102     def test_no_registry_on_request(self):
103         self._registerImpl(dummy_negotiator)
104         request = DummyRequest()
105         result = self._callFUT(request)
106         self.assertEqual(result, 'bogus')
107
108     def test_with_registry_on_request(self):
b60bdb 109         from pyramid.threadlocal import get_current_registry
7534ba 110         registry = get_current_registry()
CM 111         self._registerImpl(dummy_negotiator)
112         request = DummyRequest()
113         request.registry = registry
114         result = self._callFUT(request)
115         self.assertEqual(result, 'bogus')
116
117     def test_default_from_settings(self):
b60bdb 118         from pyramid.threadlocal import get_current_registry
7534ba 119         registry = get_current_registry()
CM 120         settings = {'default_locale_name':'settings'}
5a972b 121         registry.settings = settings
7534ba 122         request = DummyRequest()
CM 123         request.registry = registry
124         result = self._callFUT(request)
125         self.assertEqual(result, 'settings')
126
12cb6d 127     def test_use_default_locale_negotiator(self):
b60bdb 128         from pyramid.threadlocal import get_current_registry
12cb6d 129         registry = get_current_registry()
CM 130         request = DummyRequest()
131         request.registry = registry
132         request._LOCALE_ = 'locale'
133         result = self._callFUT(request)
134         self.assertEqual(result, 'locale')
135
7534ba 136     def test_default_default(self):
CM 137         request = DummyRequest()
138         result = self._callFUT(request)
139         self.assertEqual(result, 'en')
140
141 class Test_get_locale_name(unittest.TestCase):
142     def setUp(self):
330164 143         testing.setUp()
7534ba 144
CM 145     def tearDown(self):
330164 146         testing.tearDown()
7534ba 147
CM 148     def _callFUT(self, request):
b60bdb 149         from pyramid.i18n import get_locale_name
7534ba 150         return get_locale_name(request)
CM 151
152     def test_name_on_request(self):
153         request = DummyRequest()
8129f9 154         request.locale_name = 'ie'
7534ba 155         result = self._callFUT(request)
CM 156         self.assertEqual(result, 'ie')
157
86bbe8 158 class Test_make_localizer(unittest.TestCase):
CL 159     def setUp(self):
330164 160         testing.setUp()
86bbe8 161
CL 162     def tearDown(self):
330164 163         testing.tearDown()
86bbe8 164
CL 165     def _callFUT(self, locale, tdirs):
166         from pyramid.i18n import make_localizer
167         return make_localizer(locale, tdirs)
168
169     def test_locale_from_mo(self):
170         from pyramid.i18n import Localizer
171         localedirs = [localedir]
172         locale_name = 'de'
173         result = self._callFUT(locale_name, localedirs)
174         self.assertEqual(result.__class__, Localizer)
175         self.assertEqual(result.translate('Approve', 'deformsite'),
176                          'Genehmigen')
177         self.assertEqual(result.translate('Approve'), 'Approve')
a1d395 178         self.assertTrue(hasattr(result, 'pluralize'))
86bbe8 179
CL 180     def test_locale_from_mo_bad_mo(self):
181         from pyramid.i18n import Localizer
182         localedirs = [localedir]
183         locale_name = 'be'
a6e30e 184         result = self._callFUT(locale_name, localedirs)
CM 185         self.assertEqual(result.__class__, Localizer)
186         self.assertEqual(result.translate('Approve', 'deformsite'),
187                          'Approve')
188
189     def test_locale_from_mo_mo_isdir(self):
190         from pyramid.i18n import Localizer
191         localedirs = [localedir]
192         locale_name = 'gb'
86bbe8 193         result = self._callFUT(locale_name, localedirs)
CL 194         self.assertEqual(result.__class__, Localizer)
195         self.assertEqual(result.translate('Approve', 'deformsite'),
196                          'Approve')
197
f3e62c 198     def test_territory_fallback(self):
WA 199         from pyramid.i18n import Localizer
200         localedirs = [localedir]
201         locale_name = 'de_DE'
202         result = self._callFUT(locale_name, localedirs)
203         self.assertEqual(result.__class__, Localizer)
58ca44 204         self.assertEqual(result.translate('Submit', 'deformsite'),
CM 205                          'different') # prefer translations from de_DE locale
f3e62c 206         self.assertEqual(result.translate('Approve', 'deformsite'),
58ca44 207                          'Genehmigen') # missing from de_DE locale, but in de
f3e62c 208
7534ba 209 class Test_get_localizer(unittest.TestCase):
CM 210     def setUp(self):
330164 211         testing.setUp()
7534ba 212
CM 213     def tearDown(self):
330164 214         testing.tearDown()
7534ba 215
CM 216     def _callFUT(self, request):
b60bdb 217         from pyramid.i18n import get_localizer
7534ba 218         return get_localizer(request)
CM 219
330164 220     def test_it(self):
1e8358 221         request = DummyRequest()
330164 222         request.localizer = 'localizer'
CM 223         self.assertEqual(self._callFUT(request), 'localizer')
c614ff 224
7534ba 225 class Test_default_locale_negotiator(unittest.TestCase):
CM 226     def setUp(self):
330164 227         testing.setUp()
7534ba 228
CM 229     def tearDown(self):
330164 230         testing.tearDown()
7534ba 231
CM 232     def _callFUT(self, request):
b60bdb 233         from pyramid.i18n import default_locale_negotiator
7534ba 234         return default_locale_negotiator(request)
CM 235
12cb6d 236     def test_from_none(self):
7534ba 237         request = DummyRequest()
CM 238         result = self._callFUT(request)
12cb6d 239         self.assertEqual(result, None)
CM 240
241     def test_from_request_attr(self):
7534ba 242         request = DummyRequest()
12cb6d 243         request._LOCALE_ = 'foo'
7534ba 244         result = self._callFUT(request)
12cb6d 245         self.assertEqual(result, 'foo')
CM 246
7534ba 247     def test_from_params(self):
CM 248         request = DummyRequest()
12cb6d 249         request.params['_LOCALE_'] = 'foo'
CM 250         result = self._callFUT(request)
251         self.assertEqual(result, 'foo')
252
253     def test_from_cookies(self):
254         request = DummyRequest()
255         request.cookies['_LOCALE_'] = 'foo'
7534ba 256         result = self._callFUT(request)
CM 257         self.assertEqual(result, 'foo')
258
259 class TestTranslations(unittest.TestCase):
260     def _getTargetClass(self):
b60bdb 261         from pyramid.i18n import Translations
7534ba 262         return Translations
CM 263         
264     def _makeOne(self):
265         messages1 = [
266             ('foo', 'Voh'),
267             (('foo1', 1), 'Voh1'),
268         ]
269         messages2 = [
270             ('foo', 'VohD'),
271             (('foo1', 1), 'VohD1'),
272         ]
273
274         klass = self._getTargetClass()
275         
276         translations1 = klass(None, domain='messages')
277         translations1._catalog = dict(messages1)
278         translations1.plural = lambda *arg: 1
279         translations2 = klass(None, domain='messages1')
280         translations2._catalog = dict(messages2)
281         translations2.plural = lambda *arg: 1
282         translations = translations1.add(translations2, merge=False)
283         return translations
284
a6e30e 285     def test_load_locales_None(self):
CM 286         import gettext
287         klass = self._getTargetClass()
288         result = klass.load(localedir, None, domain=None)
289         self.assertEqual(result.__class__, gettext.NullTranslations)
290
7534ba 291     def test_load_domain_None(self):
CM 292         import gettext
293         locales = ['de', 'en']
294         klass = self._getTargetClass()
295         result = klass.load(localedir, locales, domain=None)
296         self.assertEqual(result.__class__, gettext.NullTranslations)
297
298     def test_load_found_locale_and_domain(self):
299         locales = ['de', 'en']
300         klass = self._getTargetClass()
301         result = klass.load(localedir, locales, domain='deformsite')
302         self.assertEqual(result.__class__, klass)
303
304     def test_load_found_locale_and_domain_locale_is_string(self):
305         locales = 'de'
306         klass = self._getTargetClass()
307         result = klass.load(localedir, locales, domain='deformsite')
308         self.assertEqual(result.__class__, klass)
309
310     def test___repr__(self):
311         inst = self._makeOne()
312         result = repr(inst)
313         self.assertEqual(result, '<Translations: "None">')
314
315     def test_merge_not_gnutranslations(self):
316         inst = self._makeOne()
317         self.assertEqual(inst.merge(None), inst)
318
319     def test_merge_gnutranslations(self):
320         inst = self._makeOne()
321         inst2 = self._makeOne()
322         inst2._catalog['a'] = 'b'
323         inst.merge(inst2)
324         self.assertEqual(inst._catalog['a'], 'b')
325
a6e30e 326     def test_merge_gnutranslations_not_translations(self):
CM 327         import gettext
328         t = gettext.GNUTranslations()
329         t._catalog = {'a':'b'}
330         inst = self._makeOne()
331         inst.merge(t)
332         self.assertEqual(inst._catalog['a'], 'b')
333
7534ba 334     def test_add_different_domain_merge_true_notexisting(self):
CM 335         inst = self._makeOne()
336         inst2 = self._makeOne()
337         inst2.domain = 'domain2'
338         inst.add(inst2)
339         self.assertEqual(inst._domains['domain2'], inst2)
340
341     def test_add_different_domain_merge_true_existing(self):
342         inst = self._makeOne()
343         inst2 = self._makeOne()
344         inst3 = self._makeOne()
345         inst2.domain = 'domain2'
346         inst2._catalog['a'] = 'b'
347         inst3.domain = 'domain2'
348         inst._domains['domain2'] = inst3
349         inst.add(inst2)
350         self.assertEqual(inst._domains['domain2'], inst3)
351         self.assertEqual(inst3._catalog['a'], 'b')
352
353     def test_add_same_domain_merge_true(self):
354         inst = self._makeOne()
355         inst2 = self._makeOne()
356         inst2._catalog['a'] = 'b'
357         inst.add(inst2)
358         self.assertEqual(inst._catalog['a'], 'b')
359
bff312 360     def test_add_default_domain_replaces_plural_first_time(self):
MW 361         # Create three empty message catalogs in the default domain
362         inst = self._getTargetClass()(None, domain='messages')
363         inst2 = self._getTargetClass()(None, domain='messages')
364         inst3 = self._getTargetClass()(None, domain='messages')
365         inst._catalog = {}
366         inst2._catalog = {}
367         inst3._catalog = {}
368
369         # The default plural scheme is the germanic one
370         self.assertEqual(inst.plural(0), 1)
371         self.assertEqual(inst.plural(1), 0)
372         self.assertEqual(inst.plural(2), 1)
373
374         # inst2 represents a message file that declares french plurals
375         inst2.plural = lambda n: n > 1
376         inst.add(inst2)
377         # that plural rule should now apply to inst
378         self.assertEqual(inst.plural(0), 0)
379         self.assertEqual(inst.plural(1), 0)
380         self.assertEqual(inst.plural(2), 1)
381
382         # We load a second message file with different plural rules
383         inst3.plural = lambda n: n > 0
384         inst.add(inst3)
385         # It doesn't override the previously loaded rule
386         self.assertEqual(inst.plural(0), 0)
387         self.assertEqual(inst.plural(1), 0)
388         self.assertEqual(inst.plural(2), 1)
389
7534ba 390     def test_dgettext(self):
CM 391         t = self._makeOne()
392         self.assertEqual(t.dgettext('messages', 'foo'), 'Voh')
393         self.assertEqual(t.dgettext('messages1', 'foo'), 'VohD')
394
395     def test_ldgettext(self):
396         t = self._makeOne()
884807 397         self.assertEqual(t.ldgettext('messages', 'foo'), b'Voh')
CM 398         self.assertEqual(t.ldgettext('messages1', 'foo'), b'VohD')
7534ba 399
CM 400     def test_dugettext(self):
401         t = self._makeOne()
402         self.assertEqual(t.dugettext('messages', 'foo'), 'Voh')
403         self.assertEqual(t.dugettext('messages1', 'foo'), 'VohD')
404
405     def test_dngettext(self):
406         t = self._makeOne()
407         self.assertEqual(t.dngettext('messages', 'foo1', 'foos1', 1), 'Voh1')
408         self.assertEqual(t.dngettext('messages1', 'foo1', 'foos1', 1), 'VohD1')
409         
410     def test_ldngettext(self):
411         t = self._makeOne()
884807 412         self.assertEqual(t.ldngettext('messages', 'foo1', 'foos1', 1), b'Voh1')
CM 413         self.assertEqual(t.ldngettext('messages1', 'foo1', 'foos1', 1),b'VohD1')
7534ba 414
CM 415     def test_dungettext(self):
416         t = self._makeOne()
417         self.assertEqual(t.dungettext('messages', 'foo1', 'foos1', 1), 'Voh1')
418         self.assertEqual(t.dungettext('messages1', 'foo1', 'foos1', 1), 'VohD1')
419
5b5cd6 420     def test_default_germanic_pluralization(self):
CM 421         t = self._getTargetClass()()
422         t._catalog = {}
423         result = t.dungettext('messages', 'foo1', 'foos1', 2)
424         self.assertEqual(result, 'foos1')
425
330164 426 class TestLocalizerRequestMixin(unittest.TestCase):
CM 427     def setUp(self):
428         self.config = testing.setUp()
429
430     def tearDown(self):
431         testing.tearDown()
432
433     def _makeOne(self):
434         from pyramid.i18n import LocalizerRequestMixin
435         request = LocalizerRequestMixin()
436         request.registry = self.config.registry
437         request.cookies = {}
438         request.params = {}
439         return request
440
441     def test_default_localizer(self):
442         # `localizer` returns a default localizer for `en`
443         from pyramid.i18n import Localizer
444         request = self._makeOne()
445         self.assertEqual(request.localizer.__class__, Localizer)
446         self.assertEqual(request.locale_name, 'en')
447
448     def test_custom_localizer_for_default_locale(self):
449         from pyramid.interfaces import ILocalizer
450         dummy = object()
451         self.config.registry.registerUtility(dummy, ILocalizer, name='en')
452         request = self._makeOne()
453         self.assertEqual(request.localizer, dummy)
454
455     def test_custom_localizer_for_custom_locale(self):
456         from pyramid.interfaces import ILocalizer
457         dummy = object()
458         self.config.registry.registerUtility(dummy, ILocalizer, name='ie')
459         request = self._makeOne()
460         request._LOCALE_ = 'ie'
461         self.assertEqual(request.localizer, dummy)
462
463     def test_localizer_from_mo(self):
464         from pyramid.interfaces import ITranslationDirectories
465         from pyramid.i18n import Localizer
466         localedirs = [localedir]
467         self.config.registry.registerUtility(
468             localedirs, ITranslationDirectories)
469         request = self._makeOne()
470         request._LOCALE_ = 'de'
471         result = request.localizer
472         self.assertEqual(result.__class__, Localizer)
473         self.assertEqual(result.translate('Approve', 'deformsite'),
474                          'Genehmigen')
475         self.assertEqual(result.translate('Approve'), 'Approve')
476         self.assertTrue(hasattr(result, 'pluralize'))
477
478     def test_localizer_from_mo_bad_mo(self):
479         from pyramid.interfaces import ITranslationDirectories
480         from pyramid.i18n import Localizer
481         localedirs = [localedir]
482         self.config.registry.registerUtility(
483             localedirs, ITranslationDirectories)
484         request = self._makeOne()
485         request._LOCALE_ = 'be'
486         result = request.localizer
487         self.assertEqual(result.__class__, Localizer)
488         self.assertEqual(result.translate('Approve', 'deformsite'),
489                          'Approve')
7534ba 490
CM 491 class DummyRequest(object):
492     def __init__(self):
493         self.params = {}
12cb6d 494         self.cookies = {}
7534ba 495
CM 496 def dummy_negotiator(request):
497     return 'bogus'
498
499 class DummyTranslations(object):
500     def ugettext(self, text):
501         return text
502
884807 503     gettext = ugettext
CM 504
7534ba 505     def ungettext(self, singular, plural, n):
CM 506         return singular
884807 507
CM 508     ngettext = ungettext