1from __future__ import unicode_literals
2
3from unittest import TestCase
4from wtforms import form, TextField, validators
5from wtforms.i18n import get_translations
6from wtforms.ext.i18n import form as i18n_form
7
8
9def gettext_lower(self, s):
10    return s.lower()
11
12
13def ngettext_lower(self, singular, plural, n):
14    if n == 1:
15        return singular.lower()
16    else:
17        return plural.lower()
18
19
20class Lower_Translator(object):
21    """A fake translator that just converts everything to lowercase."""
22
23    gettext = gettext_lower
24    ngettext = ngettext_lower
25
26
27class Python2_Translator(object):
28    """A mock translator which implements python2 ugettext methods."""
29
30    ugettext = gettext_lower
31    ungettext = ngettext_lower
32
33
34class I18NTest(TestCase):
35    def test_failure(self):
36        self.assertRaises(IOError, get_translations, [])
37
38    def test_us_translation(self):
39        translations = get_translations(['en_US'])
40        self.assertEqual(translations.gettext('Invalid Mac address.'), 'Invalid MAC address.')
41
42    def _test_converter(self, translator):
43        getter = lambda x: translator
44
45        translations = get_translations([], getter=getter)
46        self.assertEqual(translations.gettext('Foo'), 'foo')
47        self.assertEqual(translations.ngettext('Foo', 'Foos', 1), 'foo')
48        self.assertEqual(translations.ngettext('Foo', 'Foos', 2), 'foos')
49        return translations
50
51    def test_python2_wrap(self):
52        translator = Python2_Translator()
53        translations = self._test_converter(translator)
54        assert translations is not translator
55
56    def test_python3_nowrap(self):
57        translator = Lower_Translator()
58        translations = self._test_converter(translator)
59        assert translations is translator
60
61
62class ClassicI18nFormTest(TestCase):
63    class F(i18n_form.Form):
64        LANGUAGES = ['en_US', 'en']
65        a = TextField(validators=[validators.Required()])
66
67    def test_form(self):
68        tcache = i18n_form.translations_cache
69        tcache.clear()
70        form = self.F()
71
72        assert ('en_US', 'en') in tcache
73        assert form._get_translations() is tcache[('en_US', 'en')]
74        assert not form.validate()
75        self.assertEqual(form.a.errors[0], 'This field is required.')
76
77        form = self.F(LANGUAGES=['es'])
78        assert ('es', ) in tcache
79        self.assertEqual(len(tcache), 2)
80        assert not form.validate()
81        self.assertEqual(form.a.errors[0], 'Este campo es obligatorio.')
82
83
84class CoreFormTest(TestCase):
85    class F(form.Form):
86        class Meta:
87            locales = ['en_US', 'en']
88        a = TextField(validators=[validators.Required()])
89
90    class F2(form.Form):
91        a = TextField(validators=[validators.Required(), validators.Length(max=3)])
92
93    class F3(form.Form):
94        a = TextField(validators=[validators.Length(max=1)])
95
96    def _common_test(self, expected_error, form_kwargs, form_class=None):
97        if not form_class:
98            form_class = self.F
99        form = form_class(**form_kwargs)
100        assert not form.validate()
101        self.assertEqual(form.a.errors[0], expected_error)
102        return form
103
104    def test_defaults(self):
105        # Test with the default language
106        form = self._common_test('This field is required.', {})
107        # Make sure we have a gettext translations context
108        self.assertNotEqual(form.a.gettext(''), '')
109
110        form = self._common_test('This field is required.', {}, self.F2)
111        assert form._get_translations() is None
112        assert form.meta.locales is False
113        self.assertEqual(form.a.gettext(''), '')
114
115    def test_fallback(self):
116        form = self._common_test('This field is required.', dict(meta=dict(locales=False)))
117        self.assertEqual(form.a.gettext(''), '')
118
119    def test_override_languages(self):
120        self._common_test('Este campo es obligatorio.', dict(meta=dict(locales=['es_ES'])))
121
122    def test_ngettext(self):
123        language_settings = [
124            (['en_US', 'en'], 'Field cannot be longer than 3 characters.', 'Field cannot be longer than 1 character.'),
125            (['de_DE', 'de'], 'Feld kann nicht l\xe4nger als 3 Zeichen sein.', 'Feld kann nicht l\xe4nger als 1 Zeichen sein.'),
126            (['et'], 'V\xe4li ei tohi olla \xfcle 3 t\xe4hem\xe4rgi pikk.', 'V\xe4li ei tohi olla \xfcle 1 t\xe4hem\xe4rgi pikk.'),
127        ]
128        for languages, match1, match2 in language_settings:
129            settings = dict(a='toolong', meta=dict(locales=languages))
130            self._common_test(match1, settings, self.F2)
131            self._common_test(match2, settings, self.F3)
132
133    def test_cache(self):
134        settings = {'meta': {'locales': ['de_DE'], 'cache_translations': True}}
135        expected = 'Dieses Feld wird ben\xf6tigt.'
136        form1 = self._common_test(expected, settings)
137        form2 = self._common_test(expected, settings)
138        assert form1.meta.get_translations(form1) is form2.meta.get_translations(form2)
139        settings['meta']['cache_translations'] = False
140        form3 = self._common_test(expected, settings)
141        assert form2.meta.get_translations(form2) is not form3.meta.get_translations(form3)
142
143
144class TranslationsTest(TestCase):
145    class F(form.Form):
146        a = TextField(validators=[validators.Length(max=5)])
147
148    class F2(form.Form):
149        def _get_translations(self):
150            return Lower_Translator()
151
152        a = TextField('', [validators.Length(max=5)])
153
154    def setUp(self):
155        self.a = self.F().a
156
157    def test_gettext(self):
158        x = "foo"
159        self.assertTrue(self.a.gettext(x) is x)
160
161    def test_ngettext(self):
162        getit = lambda n: self.a.ngettext("antelope", "antelopes", n)
163        self.assertEqual(getit(0), "antelopes")
164        self.assertEqual(getit(1), "antelope")
165        self.assertEqual(getit(2), "antelopes")
166
167    def test_validator_translation(self):
168        form = self.F2(a='hellobye')
169        self.assertFalse(form.validate())
170        self.assertEqual(form.a.errors[0], 'field cannot be longer than 5 characters.')
171        form = self.F(a='hellobye')
172        self.assertFalse(form.validate())
173        self.assertEqual(form.a.errors[0], 'Field cannot be longer than 5 characters.')
174