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