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