0001 import os 0002 import base64 0003 import shutil 0004 import gettext 0005 import unittest 0006 0007 from test.test_support import run_suite 0008 0009 0010 # TODO: 0011 # - Add new tests, for example for "dgettext" 0012 # - Remove dummy tests, for example testing for single and double quotes 0013 # has no sense, it would have if we were testing a parser (i.e. pygettext) 0014 # - Tests should have only one assert. 0015 0016 GNU_MO_DATA = '''\ 0017 3hIElQAAAAAGAAAAHAAAAEwAAAALAAAAfAAAAAAAAACoAAAAFQAAAKkAAAAjAAAAvwAAAKEAAADj 0018 AAAABwAAAIUBAAALAAAAjQEAAEUBAACZAQAAFgAAAN8CAAAeAAAA9gIAAKEAAAAVAwAABQAAALcD 0019 AAAJAAAAvQMAAAEAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABQAAAAYAAAACAAAAAFJh 0020 eW1vbmQgTHV4dXJ5IFlhY2gtdABUaGVyZSBpcyAlcyBmaWxlAFRoZXJlIGFyZSAlcyBmaWxlcwBU 0021 aGlzIG1vZHVsZSBwcm92aWRlcyBpbnRlcm5hdGlvbmFsaXphdGlvbiBhbmQgbG9jYWxpemF0aW9u 0022 CnN1cHBvcnQgZm9yIHlvdXIgUHl0aG9uIHByb2dyYW1zIGJ5IHByb3ZpZGluZyBhbiBpbnRlcmZh 0023 Y2UgdG8gdGhlIEdOVQpnZXR0ZXh0IG1lc3NhZ2UgY2F0YWxvZyBsaWJyYXJ5LgBtdWxsdXNrAG51 0024 ZGdlIG51ZGdlAFByb2plY3QtSWQtVmVyc2lvbjogMi4wClBPLVJldmlzaW9uLURhdGU6IDIwMDAt 0025 MDgtMjkgMTI6MTktMDQ6MDAKTGFzdC1UcmFuc2xhdG9yOiBKLiBEYXZpZCBJYsOhw7FleiA8ai1k 0026 YXZpZEBub29zLmZyPgpMYW5ndWFnZS1UZWFtOiBYWCA8cHl0aG9uLWRldkBweXRob24ub3JnPgpN 0027 SU1FLVZlcnNpb246IDEuMApDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9aXNvLTg4 0028 NTktMQpDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBub25lCkdlbmVyYXRlZC1CeTogcHlnZXR0 0029 ZXh0LnB5IDEuMQpQbHVyYWwtRm9ybXM6IG5wbHVyYWxzPTI7IHBsdXJhbD1uIT0xOwoAVGhyb2F0 0030 d29iYmxlciBNYW5ncm92ZQBIYXkgJXMgZmljaGVybwBIYXkgJXMgZmljaGVyb3MAR3V2ZiB6YnFo 0031 eXIgY2ViaXZxcmYgdmFncmVhbmd2YmFueXZtbmd2YmEgbmFxIHlicG55dm1uZ3ZiYQpmaGNjYmVn 0032 IHNiZSBsYmhlIENsZ3ViYSBjZWJ0ZW56ZiBvbCBjZWJpdnF2YXQgbmEgdmFncmVzbnByIGdiIGd1 0033 ciBUQUgKdHJnZ3JrZyB6cmZmbnRyIHBuZ255YnQgeXZvZW5lbC4AYmFjb24Ad2luayB3aW5rAA== 0034 ''' 0035 0036 UMO_DATA = '''\ 0037 3hIElQAAAAACAAAAHAAAACwAAAAFAAAAPAAAAAAAAABQAAAABAAAAFEAAAAPAQAAVgAAAAQAAABm 0038 AQAAAQAAAAIAAAAAAAAAAAAAAAAAAAAAYWLDngBQcm9qZWN0LUlkLVZlcnNpb246IDIuMApQTy1S 0039 ZXZpc2lvbi1EYXRlOiAyMDAzLTA0LTExIDEyOjQyLTA0MDAKTGFzdC1UcmFuc2xhdG9yOiBCYXJy 0040 eSBBLiBXQXJzYXcgPGJhcnJ5QHB5dGhvbi5vcmc+Ckxhbmd1YWdlLVRlYW06IFhYIDxweXRob24t 0041 ZGV2QHB5dGhvbi5vcmc+Ck1JTUUtVmVyc2lvbjogMS4wCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFp 0042 bjsgY2hhcnNldD11dGYtOApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiA3Yml0CkdlbmVyYXRl 0043 ZC1CeTogbWFudWFsbHkKAMKkeXoA 0044 ''' 0045 0046 MMO_DATA = '''\ 0047 3hIElQAAAAABAAAAHAAAACQAAAADAAAALAAAAAAAAAA4AAAAeAEAADkAAAABAAAAAAAAAAAAAAAA 0048 UHJvamVjdC1JZC1WZXJzaW9uOiBObyBQcm9qZWN0IDAuMApQT1QtQ3JlYXRpb24tRGF0ZTogV2Vk 0049 IERlYyAxMSAwNzo0NDoxNSAyMDAyClBPLVJldmlzaW9uLURhdGU6IDIwMDItMDgtMTQgMDE6MTg6 0050 NTgrMDA6MDAKTGFzdC1UcmFuc2xhdG9yOiBKb2huIERvZSA8amRvZUBleGFtcGxlLmNvbT4KSmFu 0051 ZSBGb29iYXIgPGpmb29iYXJAZXhhbXBsZS5jb20+Ckxhbmd1YWdlLVRlYW06IHh4IDx4eEBleGFt 0052 cGxlLmNvbT4KTUlNRS1WZXJzaW9uOiAxLjAKQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFy 0053 c2V0PWlzby04ODU5LTE1CkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IHF1b3RlZC1wcmludGFi 0054 bGUKR2VuZXJhdGVkLUJ5OiBweWdldHRleHQucHkgMS4zCgA= 0055 ''' 0056 0057 LOCALEDIR = os.path.join('xx', 'LC_MESSAGES') 0058 MOFILE = os.path.join(LOCALEDIR, 'gettext.mo') 0059 UMOFILE = os.path.join(LOCALEDIR, 'ugettext.mo') 0060 MMOFILE = os.path.join(LOCALEDIR, 'metadata.mo') 0061 try: 0062 LANG = os.environ['LANGUAGE'] 0063 except: 0064 LANG = 'en' 0065 0066 0067 class GettextBaseTest(unittest.TestCase): 0068 def setUp(self): 0069 if not os.path.isdir(LOCALEDIR): 0070 os.makedirs(LOCALEDIR) 0071 fp = open(MOFILE, 'wb') 0072 fp.write(base64.decodestring(GNU_MO_DATA)) 0073 fp.close() 0074 fp = open(UMOFILE, 'wb') 0075 fp.write(base64.decodestring(UMO_DATA)) 0076 fp.close() 0077 fp = open(MMOFILE, 'wb') 0078 fp.write(base64.decodestring(MMO_DATA)) 0079 fp.close() 0080 os.environ['LANGUAGE'] = 'xx' 0081 0082 def tearDown(self): 0083 os.environ['LANGUAGE'] = LANG 0084 shutil.rmtree(os.path.split(LOCALEDIR)[0]) 0085 0086 0087 class GettextTestCase1(GettextBaseTest): 0088 def setUp(self): 0089 GettextBaseTest.setUp(self) 0090 self.localedir = os.curdir 0091 self.mofile = MOFILE 0092 gettext.install('gettext', self.localedir) 0093 0094 def test_some_translations(self): 0095 eq = self.assertEqual 0096 # test some translations 0097 eq(_('albatross'), 'albatross') 0098 eq(_(u'mullusk'), 'bacon') 0099 eq(_(r'Raymond Luxury Yach-t'), 'Throatwobbler Mangrove') 0100 eq(_(ur'nudge nudge'), 'wink wink') 0101 0102 def test_double_quotes(self): 0103 eq = self.assertEqual 0104 # double quotes 0105 eq(_("albatross"), 'albatross') 0106 eq(_(u"mullusk"), 'bacon') 0107 eq(_(r"Raymond Luxury Yach-t"), 'Throatwobbler Mangrove') 0108 eq(_(ur"nudge nudge"), 'wink wink') 0109 0110 def test_triple_single_quotes(self): 0111 eq = self.assertEqual 0112 # triple single quotes 0113 eq(_('''albatross'''), 'albatross') 0114 eq(_(u'''mullusk'''), 'bacon') 0115 eq(_(r'''Raymond Luxury Yach-t'''), 'Throatwobbler Mangrove') 0116 eq(_(ur'''nudge nudge'''), 'wink wink') 0117 0118 def test_triple_double_quotes(self): 0119 eq = self.assertEqual 0120 # triple double quotes 0121 eq(_("""albatross"""), 'albatross') 0122 eq(_(u"""mullusk"""), 'bacon') 0123 eq(_(r"""Raymond Luxury Yach-t"""), 'Throatwobbler Mangrove') 0124 eq(_(ur"""nudge nudge"""), 'wink wink') 0125 0126 def test_multiline_strings(self): 0127 eq = self.assertEqual 0128 # multiline strings 0129 eq(_('''This module provides internationalization and localization 0130 support for your Python programs by providing an interface to the GNU 0131 gettext message catalog library.'''), 0132 '''Guvf zbqhyr cebivqrf vagreangvbanyvmngvba naq ybpnyvmngvba 0133 fhccbeg sbe lbhe Clguba cebtenzf ol cebivqvat na vagresnpr gb gur TAH 0134 trggrkg zrffntr pngnybt yvoenel.''') 0135 0136 def test_the_alternative_interface(self): 0137 eq = self.assertEqual 0138 # test the alternative interface 0139 fp = open(self.mofile, 'rb') 0140 t = gettext.GNUTranslations(fp) 0141 fp.close() 0142 # Install the translation object 0143 t.install() 0144 eq(_('nudge nudge'), 'wink wink') 0145 # Try unicode return type 0146 t.install(unicode=True) 0147 eq(_('mullusk'), 'bacon') 0148 0149 0150 class GettextTestCase2(GettextBaseTest): 0151 def setUp(self): 0152 GettextBaseTest.setUp(self) 0153 self.localedir = os.curdir 0154 # Set up the bindings 0155 gettext.bindtextdomain('gettext', self.localedir) 0156 gettext.textdomain('gettext') 0157 # For convenience 0158 self._ = gettext.gettext 0159 0160 def test_bindtextdomain(self): 0161 self.assertEqual(gettext.bindtextdomain('gettext'), self.localedir) 0162 0163 def test_textdomain(self): 0164 self.assertEqual(gettext.textdomain(), 'gettext') 0165 0166 def test_some_translations(self): 0167 eq = self.assertEqual 0168 # test some translations 0169 eq(self._('albatross'), 'albatross') 0170 eq(self._(u'mullusk'), 'bacon') 0171 eq(self._(r'Raymond Luxury Yach-t'), 'Throatwobbler Mangrove') 0172 eq(self._(ur'nudge nudge'), 'wink wink') 0173 0174 def test_double_quotes(self): 0175 eq = self.assertEqual 0176 # double quotes 0177 eq(self._("albatross"), 'albatross') 0178 eq(self._(u"mullusk"), 'bacon') 0179 eq(self._(r"Raymond Luxury Yach-t"), 'Throatwobbler Mangrove') 0180 eq(self._(ur"nudge nudge"), 'wink wink') 0181 0182 def test_triple_single_quotes(self): 0183 eq = self.assertEqual 0184 # triple single quotes 0185 eq(self._('''albatross'''), 'albatross') 0186 eq(self._(u'''mullusk'''), 'bacon') 0187 eq(self._(r'''Raymond Luxury Yach-t'''), 'Throatwobbler Mangrove') 0188 eq(self._(ur'''nudge nudge'''), 'wink wink') 0189 0190 def test_triple_double_quotes(self): 0191 eq = self.assertEqual 0192 # triple double quotes 0193 eq(self._("""albatross"""), 'albatross') 0194 eq(self._(u"""mullusk"""), 'bacon') 0195 eq(self._(r"""Raymond Luxury Yach-t"""), 'Throatwobbler Mangrove') 0196 eq(self._(ur"""nudge nudge"""), 'wink wink') 0197 0198 def test_multiline_strings(self): 0199 eq = self.assertEqual 0200 # multiline strings 0201 eq(self._('''This module provides internationalization and localization 0202 support for your Python programs by providing an interface to the GNU 0203 gettext message catalog library.'''), 0204 '''Guvf zbqhyr cebivqrf vagreangvbanyvmngvba naq ybpnyvmngvba 0205 fhccbeg sbe lbhe Clguba cebtenzf ol cebivqvat na vagresnpr gb gur TAH 0206 trggrkg zrffntr pngnybt yvoenel.''') 0207 0208 0209 class PluralFormsTestCase(GettextBaseTest): 0210 def setUp(self): 0211 GettextBaseTest.setUp(self) 0212 self.mofile = MOFILE 0213 0214 def test_plural_forms1(self): 0215 eq = self.assertEqual 0216 x = gettext.ngettext('There is %s file', 'There are %s files', 1) 0217 eq(x, 'Hay %s fichero') 0218 x = gettext.ngettext('There is %s file', 'There are %s files', 2) 0219 eq(x, 'Hay %s ficheros') 0220 0221 def test_plural_forms2(self): 0222 eq = self.assertEqual 0223 fp = open(self.mofile, 'rb') 0224 t = gettext.GNUTranslations(fp) 0225 fp.close() 0226 x = t.ngettext('There is %s file', 'There are %s files', 1) 0227 eq(x, 'Hay %s fichero') 0228 x = t.ngettext('There is %s file', 'There are %s files', 2) 0229 eq(x, 'Hay %s ficheros') 0230 0231 def test_hu(self): 0232 eq = self.assertEqual 0233 f = gettext.c2py('0') 0234 s = ''.join([ str(f(x)) for x in range(200) ]) 0235 eq(s, "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") 0236 0237 def test_de(self): 0238 eq = self.assertEqual 0239 f = gettext.c2py('n != 1') 0240 s = ''.join([ str(f(x)) for x in range(200) ]) 0241 eq(s, "10111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") 0242 0243 def test_fr(self): 0244 eq = self.assertEqual 0245 f = gettext.c2py('n>1') 0246 s = ''.join([ str(f(x)) for x in range(200) ]) 0247 eq(s, "00111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") 0248 0249 def test_gd(self): 0250 eq = self.assertEqual 0251 f = gettext.c2py('n==1 ? 0 : n==2 ? 1 : 2') 0252 s = ''.join([ str(f(x)) for x in range(200) ]) 0253 eq(s, "20122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222") 0254 0255 def test_gd2(self): 0256 eq = self.assertEqual 0257 # Tests the combination of parentheses and "?:" 0258 f = gettext.c2py('n==1 ? 0 : (n==2 ? 1 : 2)') 0259 s = ''.join([ str(f(x)) for x in range(200) ]) 0260 eq(s, "20122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222") 0261 0262 def test_lt(self): 0263 eq = self.assertEqual 0264 f = gettext.c2py('n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2') 0265 s = ''.join([ str(f(x)) for x in range(200) ]) 0266 eq(s, "20111111112222222222201111111120111111112011111111201111111120111111112011111111201111111120111111112011111111222222222220111111112011111111201111111120111111112011111111201111111120111111112011111111") 0267 0268 def test_ru(self): 0269 eq = self.assertEqual 0270 f = gettext.c2py('n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2') 0271 s = ''.join([ str(f(x)) for x in range(200) ]) 0272 eq(s, "20111222222222222222201112222220111222222011122222201112222220111222222011122222201112222220111222222011122222222222222220111222222011122222201112222220111222222011122222201112222220111222222011122222") 0273 0274 def test_pl(self): 0275 eq = self.assertEqual 0276 f = gettext.c2py('n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2') 0277 s = ''.join([ str(f(x)) for x in range(200) ]) 0278 eq(s, "20111222222222222222221112222222111222222211122222221112222222111222222211122222221112222222111222222211122222222222222222111222222211122222221112222222111222222211122222221112222222111222222211122222") 0279 0280 def test_sl(self): 0281 eq = self.assertEqual 0282 f = gettext.c2py('n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3') 0283 s = ''.join([ str(f(x)) for x in range(200) ]) 0284 eq(s, "30122333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333012233333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333") 0285 0286 def test_security(self): 0287 raises = self.assertRaises 0288 # Test for a dangerous expression 0289 raises(ValueError, gettext.c2py, "os.chmod('/etc/passwd',0777)") 0290 0291 0292 class UnicodeTranslationsTest(GettextBaseTest): 0293 def setUp(self): 0294 GettextBaseTest.setUp(self) 0295 fp = open(UMOFILE, 'rb') 0296 try: 0297 self.t = gettext.GNUTranslations(fp) 0298 finally: 0299 fp.close() 0300 self._ = self.t.ugettext 0301 0302 def test_unicode_msgid(self): 0303 unless = self.failUnless 0304 unless(isinstance(self._(''), unicode)) 0305 unless(isinstance(self._(u''), unicode)) 0306 0307 def test_unicode_msgstr(self): 0308 eq = self.assertEqual 0309 eq(self._(u'ab\xde'), u'\xa4yz') 0310 0311 0312 class WeirdMetadataTest(GettextBaseTest): 0313 def setUp(self): 0314 GettextBaseTest.setUp(self) 0315 fp = open(MMOFILE, 'rb') 0316 try: 0317 try: 0318 self.t = gettext.GNUTranslations(fp) 0319 except: 0320 self.tearDown() 0321 raise 0322 finally: 0323 fp.close() 0324 0325 def test_weird_metadata(self): 0326 info = self.t.info() 0327 self.assertEqual(info['last-translator'], 0328 'John Doe <jdoe@example.com>\nJane Foobar <jfoobar@example.com>') 0329 0330 0331 def suite(): 0332 suite = unittest.TestSuite() 0333 suite.addTest(unittest.makeSuite(GettextTestCase1)) 0334 suite.addTest(unittest.makeSuite(GettextTestCase2)) 0335 suite.addTest(unittest.makeSuite(PluralFormsTestCase)) 0336 suite.addTest(unittest.makeSuite(UnicodeTranslationsTest)) 0337 suite.addTest(unittest.makeSuite(WeirdMetadataTest)) 0338 return suite 0339 0340 0341 def test_main(): 0342 run_suite(suite()) 0343 0344 0345 if __name__ == '__main__': 0346 test_main() 0347 0348 0349 # For reference, here's the .po file used to created the GNU_MO_DATA above. 0350 # 0351 # The original version was automatically generated from the sources with 0352 # pygettext. Later it was manually modified to add plural forms support. 0353 0354 ''' 0355 # Dummy translation for the Python test_gettext.py module. 0356 # Copyright (C) 2001 Python Software Foundation 0357 # Barry Warsaw <barry@python.org>, 2000. 0358 # 0359 msgid "" 0360 msgstr "" 0361 "Project-Id-Version: 2.0\n" 0362 "PO-Revision-Date: 2003-04-11 14:32-0400\n" 0363 "Last-Translator: J. David Ibanez <j-david@noos.fr>\n" 0364 "Language-Team: XX <python-dev@python.org>\n" 0365 "MIME-Version: 1.0\n" 0366 "Content-Type: text/plain; charset=iso-8859-1\n" 0367 "Content-Transfer-Encoding: 8bit\n" 0368 "Generated-By: pygettext.py 1.1\n" 0369 "Plural-Forms: nplurals=2; plural=n!=1;\n" 0370 0371 #: test_gettext.py:19 test_gettext.py:25 test_gettext.py:31 test_gettext.py:37 0372 #: test_gettext.py:51 test_gettext.py:80 test_gettext.py:86 test_gettext.py:92 0373 #: test_gettext.py:98 0374 msgid "nudge nudge" 0375 msgstr "wink wink" 0376 0377 #: test_gettext.py:16 test_gettext.py:22 test_gettext.py:28 test_gettext.py:34 0378 #: test_gettext.py:77 test_gettext.py:83 test_gettext.py:89 test_gettext.py:95 0379 msgid "albatross" 0380 msgstr "" 0381 0382 #: test_gettext.py:18 test_gettext.py:24 test_gettext.py:30 test_gettext.py:36 0383 #: test_gettext.py:79 test_gettext.py:85 test_gettext.py:91 test_gettext.py:97 0384 msgid "Raymond Luxury Yach-t" 0385 msgstr "Throatwobbler Mangrove" 0386 0387 #: test_gettext.py:17 test_gettext.py:23 test_gettext.py:29 test_gettext.py:35 0388 #: test_gettext.py:56 test_gettext.py:78 test_gettext.py:84 test_gettext.py:90 0389 #: test_gettext.py:96 0390 msgid "mullusk" 0391 msgstr "bacon" 0392 0393 #: test_gettext.py:40 test_gettext.py:101 0394 msgid "" 0395 "This module provides internationalization and localization\n" 0396 "support for your Python programs by providing an interface to the GNU\n" 0397 "gettext message catalog library." 0398 msgstr "" 0399 "Guvf zbqhyr cebivqrf vagreangvbanyvmngvba naq ybpnyvmngvba\n" 0400 "fhccbeg sbe lbhe Clguba cebtenzf ol cebivqvat na vagresnpr gb gur TAH\n" 0401 "trggrkg zrffntr pngnybt yvoenel." 0402 0403 # Manually added, as neither pygettext nor xgettext support plural forms 0404 # in Python. 0405 msgid "There is %s file" 0406 msgid_plural "There are %s files" 0407 msgstr[0] "Hay %s fichero" 0408 msgstr[1] "Hay %s ficheros" 0409 ''' 0410 0411 # Here's the second example po file example, used to generate the UMO_DATA 0412 # containing utf-8 encoded Unicode strings 0413 0414 ''' 0415 # Dummy translation for the Python test_gettext.py module. 0416 # Copyright (C) 2001 Python Software Foundation 0417 # Barry Warsaw <barry@python.org>, 2000. 0418 # 0419 msgid "" 0420 msgstr "" 0421 "Project-Id-Version: 2.0\n" 0422 "PO-Revision-Date: 2003-04-11 12:42-0400\n" 0423 "Last-Translator: Barry A. WArsaw <barry@python.org>\n" 0424 "Language-Team: XX <python-dev@python.org>\n" 0425 "MIME-Version: 1.0\n" 0426 "Content-Type: text/plain; charset=utf-8\n" 0427 "Content-Transfer-Encoding: 7bit\n" 0428 "Generated-By: manually\n" 0429 0430 #: nofile:0 0431 msgid "ab\xc3\x9e" 0432 msgstr "\xc2\xa4yz" 0433 ''' 0434 0435 # Here's the third example po file, used to generate MMO_DATA 0436 0437 ''' 0438 msgid "" 0439 msgstr "" 0440 "Project-Id-Version: No Project 0.0\n" 0441 "POT-Creation-Date: Wed Dec 11 07:44:15 2002\n" 0442 "PO-Revision-Date: 2002-08-14 01:18:58+00:00\n" 0443 "Last-Translator: John Doe <jdoe@example.com>\n" 0444 "Jane Foobar <jfoobar@example.com>\n" 0445 "Language-Team: xx <xx@example.com>\n" 0446 "MIME-Version: 1.0\n" 0447 "Content-Type: text/plain; charset=iso-8859-15\n" 0448 "Content-Transfer-Encoding: quoted-printable\n" 0449 "Generated-By: pygettext.py 1.3\n" 0450 ''' 0451
Generated by PyXR 0.9.4