source: trunk/essentials/dev-lang/python/Lib/test/test_gettext.py@ 3226

Last change on this file since 3226 was 3225, checked in by bird, 19 years ago

Python 2.5

File size: 17.5 KB
Line 
1import os
2import base64
3import shutil
4import gettext
5import unittest
6
7from test.test_support import run_suite
8
9
10# TODO:
11# - Add new tests, for example for "dgettext"
12# - Remove dummy tests, for example testing for single and double quotes
13# has no sense, it would have if we were testing a parser (i.e. pygettext)
14# - Tests should have only one assert.
15
16GNU_MO_DATA = '''\
173hIElQAAAAAGAAAAHAAAAEwAAAALAAAAfAAAAAAAAACoAAAAFQAAAKkAAAAjAAAAvwAAAKEAAADj
18AAAABwAAAIUBAAALAAAAjQEAAEUBAACZAQAAFgAAAN8CAAAeAAAA9gIAAKEAAAAVAwAABQAAALcD
19AAAJAAAAvQMAAAEAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABQAAAAYAAAACAAAAAFJh
20eW1vbmQgTHV4dXJ5IFlhY2gtdABUaGVyZSBpcyAlcyBmaWxlAFRoZXJlIGFyZSAlcyBmaWxlcwBU
21aGlzIG1vZHVsZSBwcm92aWRlcyBpbnRlcm5hdGlvbmFsaXphdGlvbiBhbmQgbG9jYWxpemF0aW9u
22CnN1cHBvcnQgZm9yIHlvdXIgUHl0aG9uIHByb2dyYW1zIGJ5IHByb3ZpZGluZyBhbiBpbnRlcmZh
23Y2UgdG8gdGhlIEdOVQpnZXR0ZXh0IG1lc3NhZ2UgY2F0YWxvZyBsaWJyYXJ5LgBtdWxsdXNrAG51
24ZGdlIG51ZGdlAFByb2plY3QtSWQtVmVyc2lvbjogMi4wClBPLVJldmlzaW9uLURhdGU6IDIwMDAt
25MDgtMjkgMTI6MTktMDQ6MDAKTGFzdC1UcmFuc2xhdG9yOiBKLiBEYXZpZCBJYsOhw7FleiA8ai1k
26YXZpZEBub29zLmZyPgpMYW5ndWFnZS1UZWFtOiBYWCA8cHl0aG9uLWRldkBweXRob24ub3JnPgpN
27SU1FLVZlcnNpb246IDEuMApDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9aXNvLTg4
28NTktMQpDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBub25lCkdlbmVyYXRlZC1CeTogcHlnZXR0
29ZXh0LnB5IDEuMQpQbHVyYWwtRm9ybXM6IG5wbHVyYWxzPTI7IHBsdXJhbD1uIT0xOwoAVGhyb2F0
30d29iYmxlciBNYW5ncm92ZQBIYXkgJXMgZmljaGVybwBIYXkgJXMgZmljaGVyb3MAR3V2ZiB6YnFo
31eXIgY2ViaXZxcmYgdmFncmVhbmd2YmFueXZtbmd2YmEgbmFxIHlicG55dm1uZ3ZiYQpmaGNjYmVn
32IHNiZSBsYmhlIENsZ3ViYSBjZWJ0ZW56ZiBvbCBjZWJpdnF2YXQgbmEgdmFncmVzbnByIGdiIGd1
33ciBUQUgKdHJnZ3JrZyB6cmZmbnRyIHBuZ255YnQgeXZvZW5lbC4AYmFjb24Ad2luayB3aW5rAA==
34'''
35
36UMO_DATA = '''\
373hIElQAAAAACAAAAHAAAACwAAAAFAAAAPAAAAAAAAABQAAAABAAAAFEAAAAPAQAAVgAAAAQAAABm
38AQAAAQAAAAIAAAAAAAAAAAAAAAAAAAAAYWLDngBQcm9qZWN0LUlkLVZlcnNpb246IDIuMApQTy1S
39ZXZpc2lvbi1EYXRlOiAyMDAzLTA0LTExIDEyOjQyLTA0MDAKTGFzdC1UcmFuc2xhdG9yOiBCYXJy
40eSBBLiBXQXJzYXcgPGJhcnJ5QHB5dGhvbi5vcmc+Ckxhbmd1YWdlLVRlYW06IFhYIDxweXRob24t
41ZGV2QHB5dGhvbi5vcmc+Ck1JTUUtVmVyc2lvbjogMS4wCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFp
42bjsgY2hhcnNldD11dGYtOApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiA3Yml0CkdlbmVyYXRl
43ZC1CeTogbWFudWFsbHkKAMKkeXoA
44'''
45
46MMO_DATA = '''\
473hIElQAAAAABAAAAHAAAACQAAAADAAAALAAAAAAAAAA4AAAAeAEAADkAAAABAAAAAAAAAAAAAAAA
48UHJvamVjdC1JZC1WZXJzaW9uOiBObyBQcm9qZWN0IDAuMApQT1QtQ3JlYXRpb24tRGF0ZTogV2Vk
49IERlYyAxMSAwNzo0NDoxNSAyMDAyClBPLVJldmlzaW9uLURhdGU6IDIwMDItMDgtMTQgMDE6MTg6
50NTgrMDA6MDAKTGFzdC1UcmFuc2xhdG9yOiBKb2huIERvZSA8amRvZUBleGFtcGxlLmNvbT4KSmFu
51ZSBGb29iYXIgPGpmb29iYXJAZXhhbXBsZS5jb20+Ckxhbmd1YWdlLVRlYW06IHh4IDx4eEBleGFt
52cGxlLmNvbT4KTUlNRS1WZXJzaW9uOiAxLjAKQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFy
53c2V0PWlzby04ODU5LTE1CkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IHF1b3RlZC1wcmludGFi
54bGUKR2VuZXJhdGVkLUJ5OiBweWdldHRleHQucHkgMS4zCgA=
55'''
56
57LOCALEDIR = os.path.join('xx', 'LC_MESSAGES')
58MOFILE = os.path.join(LOCALEDIR, 'gettext.mo')
59UMOFILE = os.path.join(LOCALEDIR, 'ugettext.mo')
60MMOFILE = os.path.join(LOCALEDIR, 'metadata.mo')
61try:
62 LANG = os.environ['LANGUAGE']
63except:
64 LANG = 'en'
65
66
67class GettextBaseTest(unittest.TestCase):
68 def setUp(self):
69 if not os.path.isdir(LOCALEDIR):
70 os.makedirs(LOCALEDIR)
71 fp = open(MOFILE, 'wb')
72 fp.write(base64.decodestring(GNU_MO_DATA))
73 fp.close()
74 fp = open(UMOFILE, 'wb')
75 fp.write(base64.decodestring(UMO_DATA))
76 fp.close()
77 fp = open(MMOFILE, 'wb')
78 fp.write(base64.decodestring(MMO_DATA))
79 fp.close()
80 os.environ['LANGUAGE'] = 'xx'
81
82 def tearDown(self):
83 os.environ['LANGUAGE'] = LANG
84 shutil.rmtree(os.path.split(LOCALEDIR)[0])
85
86
87class GettextTestCase1(GettextBaseTest):
88 def setUp(self):
89 GettextBaseTest.setUp(self)
90 self.localedir = os.curdir
91 self.mofile = MOFILE
92 gettext.install('gettext', self.localedir)
93
94 def test_some_translations(self):
95 eq = self.assertEqual
96 # test some translations
97 eq(_('albatross'), 'albatross')
98 eq(_(u'mullusk'), 'bacon')
99 eq(_(r'Raymond Luxury Yach-t'), 'Throatwobbler Mangrove')
100 eq(_(ur'nudge nudge'), 'wink wink')
101
102 def test_double_quotes(self):
103 eq = self.assertEqual
104 # double quotes
105 eq(_("albatross"), 'albatross')
106 eq(_(u"mullusk"), 'bacon')
107 eq(_(r"Raymond Luxury Yach-t"), 'Throatwobbler Mangrove')
108 eq(_(ur"nudge nudge"), 'wink wink')
109
110 def test_triple_single_quotes(self):
111 eq = self.assertEqual
112 # triple single quotes
113 eq(_('''albatross'''), 'albatross')
114 eq(_(u'''mullusk'''), 'bacon')
115 eq(_(r'''Raymond Luxury Yach-t'''), 'Throatwobbler Mangrove')
116 eq(_(ur'''nudge nudge'''), 'wink wink')
117
118 def test_triple_double_quotes(self):
119 eq = self.assertEqual
120 # triple double quotes
121 eq(_("""albatross"""), 'albatross')
122 eq(_(u"""mullusk"""), 'bacon')
123 eq(_(r"""Raymond Luxury Yach-t"""), 'Throatwobbler Mangrove')
124 eq(_(ur"""nudge nudge"""), 'wink wink')
125
126 def test_multiline_strings(self):
127 eq = self.assertEqual
128 # multiline strings
129 eq(_('''This module provides internationalization and localization
130support for your Python programs by providing an interface to the GNU
131gettext message catalog library.'''),
132 '''Guvf zbqhyr cebivqrf vagreangvbanyvmngvba naq ybpnyvmngvba
133fhccbeg sbe lbhe Clguba cebtenzf ol cebivqvat na vagresnpr gb gur TAH
134trggrkg zrffntr pngnybt yvoenel.''')
135
136 def test_the_alternative_interface(self):
137 eq = self.assertEqual
138 # test the alternative interface
139 fp = open(self.mofile, 'rb')
140 t = gettext.GNUTranslations(fp)
141 fp.close()
142 # Install the translation object
143 t.install()
144 eq(_('nudge nudge'), 'wink wink')
145 # Try unicode return type
146 t.install(unicode=True)
147 eq(_('mullusk'), 'bacon')
148 # Test installation of other methods
149 import __builtin__
150 t.install(unicode=True, names=["gettext", "lgettext"])
151 eq(_, t.ugettext)
152 eq(__builtin__.gettext, t.ugettext)
153 eq(lgettext, t.lgettext)
154 del __builtin__.gettext
155 del __builtin__.lgettext
156
157
158class GettextTestCase2(GettextBaseTest):
159 def setUp(self):
160 GettextBaseTest.setUp(self)
161 self.localedir = os.curdir
162 # Set up the bindings
163 gettext.bindtextdomain('gettext', self.localedir)
164 gettext.textdomain('gettext')
165 # For convenience
166 self._ = gettext.gettext
167
168 def test_bindtextdomain(self):
169 self.assertEqual(gettext.bindtextdomain('gettext'), self.localedir)
170
171 def test_textdomain(self):
172 self.assertEqual(gettext.textdomain(), 'gettext')
173
174 def test_some_translations(self):
175 eq = self.assertEqual
176 # test some translations
177 eq(self._('albatross'), 'albatross')
178 eq(self._(u'mullusk'), 'bacon')
179 eq(self._(r'Raymond Luxury Yach-t'), 'Throatwobbler Mangrove')
180 eq(self._(ur'nudge nudge'), 'wink wink')
181
182 def test_double_quotes(self):
183 eq = self.assertEqual
184 # double quotes
185 eq(self._("albatross"), 'albatross')
186 eq(self._(u"mullusk"), 'bacon')
187 eq(self._(r"Raymond Luxury Yach-t"), 'Throatwobbler Mangrove')
188 eq(self._(ur"nudge nudge"), 'wink wink')
189
190 def test_triple_single_quotes(self):
191 eq = self.assertEqual
192 # triple single quotes
193 eq(self._('''albatross'''), 'albatross')
194 eq(self._(u'''mullusk'''), 'bacon')
195 eq(self._(r'''Raymond Luxury Yach-t'''), 'Throatwobbler Mangrove')
196 eq(self._(ur'''nudge nudge'''), 'wink wink')
197
198 def test_triple_double_quotes(self):
199 eq = self.assertEqual
200 # triple double quotes
201 eq(self._("""albatross"""), 'albatross')
202 eq(self._(u"""mullusk"""), 'bacon')
203 eq(self._(r"""Raymond Luxury Yach-t"""), 'Throatwobbler Mangrove')
204 eq(self._(ur"""nudge nudge"""), 'wink wink')
205
206 def test_multiline_strings(self):
207 eq = self.assertEqual
208 # multiline strings
209 eq(self._('''This module provides internationalization and localization
210support for your Python programs by providing an interface to the GNU
211gettext message catalog library.'''),
212 '''Guvf zbqhyr cebivqrf vagreangvbanyvmngvba naq ybpnyvmngvba
213fhccbeg sbe lbhe Clguba cebtenzf ol cebivqvat na vagresnpr gb gur TAH
214trggrkg zrffntr pngnybt yvoenel.''')
215
216
217class PluralFormsTestCase(GettextBaseTest):
218 def setUp(self):
219 GettextBaseTest.setUp(self)
220 self.mofile = MOFILE
221
222 def test_plural_forms1(self):
223 eq = self.assertEqual
224 x = gettext.ngettext('There is %s file', 'There are %s files', 1)
225 eq(x, 'Hay %s fichero')
226 x = gettext.ngettext('There is %s file', 'There are %s files', 2)
227 eq(x, 'Hay %s ficheros')
228
229 def test_plural_forms2(self):
230 eq = self.assertEqual
231 fp = open(self.mofile, 'rb')
232 t = gettext.GNUTranslations(fp)
233 fp.close()
234 x = t.ngettext('There is %s file', 'There are %s files', 1)
235 eq(x, 'Hay %s fichero')
236 x = t.ngettext('There is %s file', 'There are %s files', 2)
237 eq(x, 'Hay %s ficheros')
238
239 def test_hu(self):
240 eq = self.assertEqual
241 f = gettext.c2py('0')
242 s = ''.join([ str(f(x)) for x in range(200) ])
243 eq(s, "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
244
245 def test_de(self):
246 eq = self.assertEqual
247 f = gettext.c2py('n != 1')
248 s = ''.join([ str(f(x)) for x in range(200) ])
249 eq(s, "10111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")
250
251 def test_fr(self):
252 eq = self.assertEqual
253 f = gettext.c2py('n>1')
254 s = ''.join([ str(f(x)) for x in range(200) ])
255 eq(s, "00111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")
256
257 def test_gd(self):
258 eq = self.assertEqual
259 f = gettext.c2py('n==1 ? 0 : n==2 ? 1 : 2')
260 s = ''.join([ str(f(x)) for x in range(200) ])
261 eq(s, "20122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222")
262
263 def test_gd2(self):
264 eq = self.assertEqual
265 # Tests the combination of parentheses and "?:"
266 f = gettext.c2py('n==1 ? 0 : (n==2 ? 1 : 2)')
267 s = ''.join([ str(f(x)) for x in range(200) ])
268 eq(s, "20122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222")
269
270 def test_lt(self):
271 eq = self.assertEqual
272 f = gettext.c2py('n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2')
273 s = ''.join([ str(f(x)) for x in range(200) ])
274 eq(s, "20111111112222222222201111111120111111112011111111201111111120111111112011111111201111111120111111112011111111222222222220111111112011111111201111111120111111112011111111201111111120111111112011111111")
275
276 def test_ru(self):
277 eq = self.assertEqual
278 f = gettext.c2py('n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2')
279 s = ''.join([ str(f(x)) for x in range(200) ])
280 eq(s, "20111222222222222222201112222220111222222011122222201112222220111222222011122222201112222220111222222011122222222222222220111222222011122222201112222220111222222011122222201112222220111222222011122222")
281
282 def test_pl(self):
283 eq = self.assertEqual
284 f = gettext.c2py('n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2')
285 s = ''.join([ str(f(x)) for x in range(200) ])
286 eq(s, "20111222222222222222221112222222111222222211122222221112222222111222222211122222221112222222111222222211122222222222222222111222222211122222221112222222111222222211122222221112222222111222222211122222")
287
288 def test_sl(self):
289 eq = self.assertEqual
290 f = gettext.c2py('n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3')
291 s = ''.join([ str(f(x)) for x in range(200) ])
292 eq(s, "30122333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333012233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333")
293
294 def test_security(self):
295 raises = self.assertRaises
296 # Test for a dangerous expression
297 raises(ValueError, gettext.c2py, "os.chmod('/etc/passwd',0777)")
298
299
300class UnicodeTranslationsTest(GettextBaseTest):
301 def setUp(self):
302 GettextBaseTest.setUp(self)
303 fp = open(UMOFILE, 'rb')
304 try:
305 self.t = gettext.GNUTranslations(fp)
306 finally:
307 fp.close()
308 self._ = self.t.ugettext
309
310 def test_unicode_msgid(self):
311 unless = self.failUnless
312 unless(isinstance(self._(''), unicode))
313 unless(isinstance(self._(u''), unicode))
314
315 def test_unicode_msgstr(self):
316 eq = self.assertEqual
317 eq(self._(u'ab\xde'), u'\xa4yz')
318
319
320class WeirdMetadataTest(GettextBaseTest):
321 def setUp(self):
322 GettextBaseTest.setUp(self)
323 fp = open(MMOFILE, 'rb')
324 try:
325 try:
326 self.t = gettext.GNUTranslations(fp)
327 except:
328 self.tearDown()
329 raise
330 finally:
331 fp.close()
332
333 def test_weird_metadata(self):
334 info = self.t.info()
335 self.assertEqual(info['last-translator'],
336 'John Doe <[email protected]>\nJane Foobar <[email protected]>')
337
338
339def suite():
340 suite = unittest.TestSuite()
341 suite.addTest(unittest.makeSuite(GettextTestCase1))
342 suite.addTest(unittest.makeSuite(GettextTestCase2))
343 suite.addTest(unittest.makeSuite(PluralFormsTestCase))
344 suite.addTest(unittest.makeSuite(UnicodeTranslationsTest))
345 suite.addTest(unittest.makeSuite(WeirdMetadataTest))
346 return suite
347
348
349def test_main():
350 run_suite(suite())
351
352
353if __name__ == '__main__':
354 test_main()
355
356
357# For reference, here's the .po file used to created the GNU_MO_DATA above.
358#
359# The original version was automatically generated from the sources with
360# pygettext. Later it was manually modified to add plural forms support.
361
362'''
363# Dummy translation for the Python test_gettext.py module.
364# Copyright (C) 2001 Python Software Foundation
365# Barry Warsaw <[email protected]>, 2000.
366#
367msgid ""
368msgstr ""
369"Project-Id-Version: 2.0\n"
370"PO-Revision-Date: 2003-04-11 14:32-0400\n"
371"Last-Translator: J. David Ibanez <[email protected]>\n"
372"Language-Team: XX <[email protected]>\n"
373"MIME-Version: 1.0\n"
374"Content-Type: text/plain; charset=iso-8859-1\n"
375"Content-Transfer-Encoding: 8bit\n"
376"Generated-By: pygettext.py 1.1\n"
377"Plural-Forms: nplurals=2; plural=n!=1;\n"
378
379#: test_gettext.py:19 test_gettext.py:25 test_gettext.py:31 test_gettext.py:37
380#: test_gettext.py:51 test_gettext.py:80 test_gettext.py:86 test_gettext.py:92
381#: test_gettext.py:98
382msgid "nudge nudge"
383msgstr "wink wink"
384
385#: test_gettext.py:16 test_gettext.py:22 test_gettext.py:28 test_gettext.py:34
386#: test_gettext.py:77 test_gettext.py:83 test_gettext.py:89 test_gettext.py:95
387msgid "albatross"
388msgstr ""
389
390#: test_gettext.py:18 test_gettext.py:24 test_gettext.py:30 test_gettext.py:36
391#: test_gettext.py:79 test_gettext.py:85 test_gettext.py:91 test_gettext.py:97
392msgid "Raymond Luxury Yach-t"
393msgstr "Throatwobbler Mangrove"
394
395#: test_gettext.py:17 test_gettext.py:23 test_gettext.py:29 test_gettext.py:35
396#: test_gettext.py:56 test_gettext.py:78 test_gettext.py:84 test_gettext.py:90
397#: test_gettext.py:96
398msgid "mullusk"
399msgstr "bacon"
400
401#: test_gettext.py:40 test_gettext.py:101
402msgid ""
403"This module provides internationalization and localization\n"
404"support for your Python programs by providing an interface to the GNU\n"
405"gettext message catalog library."
406msgstr ""
407"Guvf zbqhyr cebivqrf vagreangvbanyvmngvba naq ybpnyvmngvba\n"
408"fhccbeg sbe lbhe Clguba cebtenzf ol cebivqvat na vagresnpr gb gur TAH\n"
409"trggrkg zrffntr pngnybt yvoenel."
410
411# Manually added, as neither pygettext nor xgettext support plural forms
412# in Python.
413msgid "There is %s file"
414msgid_plural "There are %s files"
415msgstr[0] "Hay %s fichero"
416msgstr[1] "Hay %s ficheros"
417'''
418
419# Here's the second example po file example, used to generate the UMO_DATA
420# containing utf-8 encoded Unicode strings
421
422'''
423# Dummy translation for the Python test_gettext.py module.
424# Copyright (C) 2001 Python Software Foundation
425# Barry Warsaw <[email protected]>, 2000.
426#
427msgid ""
428msgstr ""
429"Project-Id-Version: 2.0\n"
430"PO-Revision-Date: 2003-04-11 12:42-0400\n"
431"Last-Translator: Barry A. WArsaw <[email protected]>\n"
432"Language-Team: XX <[email protected]>\n"
433"MIME-Version: 1.0\n"
434"Content-Type: text/plain; charset=utf-8\n"
435"Content-Transfer-Encoding: 7bit\n"
436"Generated-By: manually\n"
437
438#: nofile:0
439msgid "ab\xc3\x9e"
440msgstr "\xc2\xa4yz"
441'''
442
443# Here's the third example po file, used to generate MMO_DATA
444
445'''
446msgid ""
447msgstr ""
448"Project-Id-Version: No Project 0.0\n"
449"POT-Creation-Date: Wed Dec 11 07:44:15 2002\n"
450"PO-Revision-Date: 2002-08-14 01:18:58+00:00\n"
451"Last-Translator: John Doe <[email protected]>\n"
452"Jane Foobar <[email protected]>\n"
453"Language-Team: xx <[email protected]>\n"
454"MIME-Version: 1.0\n"
455"Content-Type: text/plain; charset=iso-8859-15\n"
456"Content-Transfer-Encoding: quoted-printable\n"
457"Generated-By: pygettext.py 1.3\n"
458'''
Note: See TracBrowser for help on using the repository browser.