1from zope.interface import implements
2
3from twisted.trial import unittest
4from cStringIO import StringIO
5from nevow import inevow, flat, context, tags, loaders, rend
6from nevow import i18n
7from nevow.testutil import FakeRequest
8
9def mockTranslator(s, languages=None, domain=None):
10    args = {}
11    if domain is not None:
12        args['domain'] = domain
13    return 'MOCK(%s)[%s]' % (', '.join(['%s=%r' % (k,v)
14                                        for k,v in args.items()]),
15                             s)
16
17class Misc(unittest.TestCase):
18    def test_simple(self):
19        s = i18n._('foo')
20
21    def test_simple_flat(self):
22        s = i18n._('foo')
23        r = flat.ten.flatten(s, None)
24        self.assertEquals(r, 'foo')
25
26    def test_translator(self):
27        _ = i18n.Translator(translator=mockTranslator)
28        s = _('foo')
29        r = flat.ten.flatten(s, None)
30        self.assertEquals(r, 'MOCK()[foo]')
31
32class Config(unittest.TestCase):
33    def test_remember(self):
34        ctx = context.WebContext()
35        cfg = i18n.I18NConfig(domain='foo')
36        ctx.remember(cfg)
37
38class Domain(unittest.TestCase):
39    def test_classInit(self):
40        _ = i18n.Translator(translator=mockTranslator,
41                            domain='bar')
42        s = _('foo')
43        r = flat.ten.flatten(s, None)
44        self.assertEquals(r, "MOCK(domain='bar')[foo]")
45
46    def test_runTime(self):
47        _ = i18n.Translator(translator=mockTranslator)
48        s = _('foo', domain='baz')
49        r = flat.ten.flatten(s, None)
50        self.assertEquals(r, "MOCK(domain='baz')[foo]")
51
52    def test_context(self):
53        _ = i18n.Translator(translator=mockTranslator)
54        ctx = context.WebContext()
55        cfg = i18n.I18NConfig(domain='thud')
56        ctx.remember(cfg)
57        s = _('foo')
58        r = flat.ten.flatten(s, ctx)
59        self.assertEquals(r, "MOCK(domain='thud')[foo]")
60
61    def test_runTime_beats_all(self):
62        _ = i18n.Translator(translator=mockTranslator,
63                            domain='not-used1')
64        ctx = context.WebContext()
65        cfg = i18n.I18NConfig(domain='not-used2')
66        ctx.remember(cfg)
67        s = _('foo', domain='baz')
68        r = flat.ten.flatten(s, None)
69        self.assertEquals(r, "MOCK(domain='baz')[foo]")
70
71
72    def test_classInit_beats_context(self):
73        _ = i18n.Translator(translator=mockTranslator,
74                            domain='baz')
75        ctx = context.WebContext()
76        cfg = i18n.I18NConfig(domain='not-used')
77        ctx.remember(cfg)
78        s = _('foo')
79        r = flat.ten.flatten(s, None)
80        self.assertEquals(r, "MOCK(domain='baz')[foo]")
81
82class Format(unittest.TestCase):
83    def test_simple(self):
84        _ = i18n.Translator(translator=mockTranslator)
85        s = _('foo %s') % 'bar'
86        r = flat.ten.flatten(s, None)
87        self.assertEquals(r, "MOCK()[foo bar]")
88
89    def test_multiple(self):
90        _ = i18n.Translator(translator=mockTranslator)
91        s = _('foo %s')
92        s = s % 'bar %s'
93        s = s % 'baz'
94        r = flat.ten.flatten(s, None)
95        self.assertEquals(r, "MOCK()[foo bar baz]")
96
97
98
99class Languages(unittest.TestCase):
100    def test_noLanguages(self):
101        request = FakeRequest(headers={})
102        ctx = context.RequestContext(tag=request)
103        r = inevow.ILanguages(ctx)
104        self.assertEquals(r, [])
105
106    def test_oneLanguage(self):
107        request = FakeRequest(headers={
108            'accept-language': 'fo',
109            })
110        ctx = context.RequestContext(tag=request)
111        r = inevow.ILanguages(ctx)
112        self.assertEquals(r, ['fo'])
113
114    def test_multipleLanguages(self):
115        request = FakeRequest(headers={
116            'accept-language': 'fo,ba,th',
117            })
118        ctx = context.RequestContext(tag=request)
119        r = inevow.ILanguages(ctx)
120        self.assertEquals(r, ['fo', 'ba', 'th'])
121
122    def test_quality_simple(self):
123        request = FakeRequest(headers={
124            'accept-language': 'fo;q=0.4',
125            })
126        ctx = context.RequestContext(tag=request)
127        r = inevow.ILanguages(ctx)
128        self.assertEquals(r, ['fo'])
129
130    def test_quality_sort(self):
131        request = FakeRequest(headers={
132            'accept-language': 'fo;q=0.4,ba;q=0.2,xy;q=0.9',
133            })
134        ctx = context.RequestContext(tag=request)
135        r = inevow.ILanguages(ctx)
136        self.assertEquals(r, ['xy', 'fo', 'ba'])
137
138    def test_quality_invalid_notQ(self):
139        request = FakeRequest(headers={
140            'accept-language': 'fo;q=0.4,ba;z=0.2',
141            })
142        ctx = context.RequestContext(tag=request)
143        r = inevow.ILanguages(ctx)
144        self.assertEquals(r, ['ba', 'fo'])
145
146    def test_quality_invalid_notFloat(self):
147        request = FakeRequest(headers={
148            'accept-language': 'fo;q=0.4,ba;q=junk',
149            })
150        ctx = context.RequestContext(tag=request)
151        r = inevow.ILanguages(ctx)
152        self.assertEquals(r, ['ba', 'fo'])
153
154class Render(unittest.TestCase):
155    def makePage(self, content):
156        _ = i18n.Translator(translator=mockTranslator)
157        page = rend.Page(
158            docFactory=loaders.stan(tags.invisible(render=tags.directive('i18n'))[content]))
159        page.render_i18n = i18n.render(_)
160        doc = page.docFactory.load()
161        ctx = context.WovenContext(context.PageContext(tag=page),
162                                   tags.invisible[doc])
163        page.rememberStuff(ctx)
164
165        io = StringIO()
166        writer = io.write
167
168        def finisher(result):
169            return io.getvalue()
170
171        return page.flattenFactory(doc, ctx, writer, finisher)
172
173    def test_empty(self):
174        return self.makePage(['']).addCallback(
175            lambda r: self.assertEquals(r, 'MOCK()[]'))
176
177    def test_simple(self):
178        return self.makePage(['foo']).addCallback(
179            lambda r: self.assertEquals(r, 'MOCK()[foo]'))
180
181    def test_stan(self):
182        return self.makePage([tags.p['You should really avoid tags in i18n input.']]).addCallback(
183            lambda r: self.assertEquals(r, 'MOCK()[<p>You should really avoid tags in i18n input.</p>]'))
184
185class InterpolateTests:
186    def test_mod_string(self):
187        self.check('foo %s', 'bar',
188                   'foo bar')
189
190    def test_mod_unicode(self):
191        self.check('foo %s', u'bar',
192                   'foo bar')
193
194    def test_mod_int(self):
195        self.check('foo %d', 42,
196                   'foo 42')
197
198    def test_mod_float(self):
199        self.check('foo %.3f', 42.0,
200                   'foo 42.000')
201
202    def test_mod_char(self):
203        self.check('foo %c', 42,
204                   'foo *')
205        self.check('foo %c', '*',
206                   'foo *')
207
208    # Tuples are a special case, 'foo %s' % ('bar', 'baz') does not
209    # work. Also, 'foo %s %s' only works with tuples.
210
211    def test_mod_tuple_two(self):
212        self.check('foo %s %s', ('bar', 'baz'),
213                   "foo bar baz")
214
215    def test_mod_tuple_complex(self):
216        self.check('foo %s %s %s', ([1, 2], (3, 4), {5: 6}),
217                   "foo [1, 2] (3, 4) {5: 6}")
218
219    def test_mod_list_stringify(self):
220        self.check('foo %s', ['bar', 'baz'],
221                   "foo ['bar', 'baz']")
222
223    def test_mod_list_reprify(self):
224        self.check('foo %r', ['bar', 'baz'],
225                   "foo ['bar', 'baz']")
226
227    def test_mod_dict_stringify(self):
228        self.check('foo %s', {'bar': 1, 'baz': 2},
229                   "foo {'bar': 1, 'baz': 2}",
230                   "foo {'baz': 2, 'bar': 1}")
231
232    def test_mod_dict_reprify(self):
233        self.check('foo %r', {'bar': 1, 'baz': 2},
234                   "foo {'bar': 1, 'baz': 2}",
235                   "foo {'baz': 2, 'bar': 1}")
236
237    def test_mod_dict_two(self):
238        self.check('foo %(bar)s %(baz)s', {'bar': 1, 'baz': 2},
239                   "foo 1 2")
240
241    def test_mod_dict_two_as_ints(self):
242        self.check('foo %(bar)d %(baz)d', {'bar': 1, 'baz': 2},
243                   "foo 1 2")
244
245    def test_mod_dict_two_as_floats(self):
246        self.check('foo %(bar).1f %(baz).1f', {'bar': 1.2, 'baz': 2.3},
247                   "foo 1.2 2.3")
248
249    def test_mod_dict_two_as_chars(self):
250        self.check('foo %(bar)c %(baz)c', {'bar': 52, 'baz': '2'},
251                   "foo 4 2")
252
253class InterpolateMixin:
254    def setUp(self):
255        self._ = i18n.Translator(translator=mockTranslator)
256
257    def mangle(self, s):
258        raise NotImplementedError, 'override mangle somewhere'
259
260    def check(self, fmt, args, *wants):
261        got = self.mangle(self._(fmt) % args)
262        self.failUnlessIn(got, wants)
263
264class Repr(InterpolateMixin, unittest.TestCase, InterpolateTests):
265    def mangle(self, s):
266        return repr(s)
267
268    def check(self, fmt, args, *wants):
269        InterpolateMixin.check(self, fmt, args,
270                               "PlaceHolder(*%r, translator=%r) %% %r" % \
271                               ((fmt,), mockTranslator, args))
272
273class Str(InterpolateMixin, unittest.TestCase, InterpolateTests):
274    def mangle(self, s):
275        return str(s)
276
277    def check(self, fmt, args, *wants):
278        InterpolateMixin.check(self, fmt, args,
279                               "PlaceHolder(*%r, translator=%r) %% %r" % \
280                               ((fmt,), mockTranslator, args))
281
282class Interpolation(InterpolateMixin, unittest.TestCase, InterpolateTests):
283    def mangle(self, s):
284        r = flat.ten.flatten(s, None)
285        return r
286
287    def check(self, fmt, args, *wants):
288        InterpolateMixin.check(self, fmt, args,
289                               *['MOCK()[%s]' % x for x in wants])
290
291class UNGettext(unittest.TestCase):
292    def test_simple(self):
293        s1 = i18n.ungettext('%d foo', '%d foos', 1)
294        s2 = i18n.ungettext('%d foo', '%d foos', 42)
295
296    def test_simple_flat_one(self):
297        s = i18n.ungettext('%d foo', '%d foos', 1)
298        r = flat.ten.flatten(s, None)
299        self.assertEquals(r, '%d foo')
300
301    def test_simple_flat_many(self):
302        s = i18n.ungettext('%d foo', '%d foos', 42)
303        r = flat.ten.flatten(s, None)
304        self.assertEquals(r, '%d foos')
305
306    def test_simple_flat_many(self):
307        s = i18n.ungettext('%d foo', '%d foos', 42)
308        r = flat.ten.flatten(s, None)
309        self.assertEquals(r, '%d foos')
310
311    def test_format_one(self):
312        s = i18n.ungettext('%d foo', '%d foos', 1) % 1
313        r = flat.ten.flatten(s, None)
314        self.assertEquals(r, "1 foo")
315
316    def test_format_many(self):
317        s = i18n.ungettext('%d foo', '%d foos', 42) % 42
318        r = flat.ten.flatten(s, None)
319        self.assertEquals(r, "42 foos")
320