def testIncompletePluralMessage(self): """Test export correctness for partial plural messages.""" pofile = dedent(''' msgid "" msgstr "" "Project-Id-Version: foo\\n" "Report-Msgid-Bugs-To: \\n" "POT-Creation-Date: 2007-07-09 03:39+0100\\n" "PO-Revision-Date: 2001-09-09 01:46+0000\\n" "Last-Translator: Kubla Kahn <*****@*****.**>\\n" "Language-Team: LANGUAGE <*****@*****.**>\\n" "MIME-Version: 1.0\\n" "Content-Type: text/plain; charset=UTF-8\\n" "Content-Transfer-Encoding: 8bit\\n" "Plural-Forms: nplurals=2; plural=(n != 1);\\n" msgid "1 dead horse" msgid_plural "%%d dead horses" msgstr[0] "ning\xc3\xban caballo muerto" %s''') translation_file = self.parser.parse(pofile % ('')) translation_file.is_template = False translation_file.language_code = 'es' translation_file.path = 'po/es.po' translation_file.translation_domain = 'testing' storage = ExportFileStorage() self.translation_exporter.exportTranslationFile( translation_file, storage) self._compareImportAndExport( pofile.strip() % 'msgstr[1] ""', storage.export().read().strip())
def testIncompletePluralMessage(self): """Test export correctness for partial plural messages.""" pofile = dedent( """ msgid "" msgstr "" "Project-Id-Version: foo\\n" "Report-Msgid-Bugs-To: \\n" "POT-Creation-Date: 2007-07-09 03:39+0100\\n" "PO-Revision-Date: 2001-09-09 01:46+0000\\n" "Last-Translator: Kubla Kahn <*****@*****.**>\\n" "Language-Team: LANGUAGE <*****@*****.**>\\n" "MIME-Version: 1.0\\n" "Content-Type: text/plain; charset=UTF-8\\n" "Content-Transfer-Encoding: 8bit\\n" "Plural-Forms: nplurals=2; plural=(n != 1);\\n" msgid "1 dead horse" msgid_plural "%%d dead horses" msgstr[0] "ning\xc3\xban caballo muerto" %s""" ) translation_file = self.parser.parse(pofile % ("")) translation_file.is_template = False translation_file.language_code = "es" translation_file.path = "po/es.po" translation_file.translation_domain = "testing" storage = ExportFileStorage() self.translation_exporter.exportTranslationFile(translation_file, storage) self._compareImportAndExport(pofile.strip() % 'msgstr[1] ""', storage.export().read().strip())
def testSingle(self): """Test export of single file.""" mime = 'application/x-po' storage = ExportFileStorage() storage.addFile('/tmp/a/test/file.po', 'po', 'test file', mime) outfile = storage.export() self.assertEquals(outfile.path, '/tmp/a/test/file.po') self.assertEquals(outfile.file_extension, 'po') self.assertEquals(outfile.read(), 'test file')
def testObsoleteExport(self): """Check how obsoleted messages are exported.""" pofile_eo = dedent( """ msgid "" msgstr "" "Project-Id-Version: Kumquats 1.0\\n" "Report-Msgid-Bugs-To: \\n" "POT-Creation-Date: 2007-07-09 03:39+0100\\n" "PO-Revision-Date: 2001-09-09 01:46+0000\\n" "Last-Translator: L.L. Zamenhoff <*****@*****.**>\\n" "Language-Team: Esperanto <*****@*****.**>\\n" "MIME-Version: 1.0\\n" "Content-Type: text/plain; charset=UTF-8\\n" "Content-Transfer-Encoding: 8bit\\n" # Foo bar. #, c-format #: src/foo.c #| msgid "zog" msgid "zig" msgstr "zag" """ ) pofile_eo_obsolete = dedent( """ msgid "" msgstr "" "Project-Id-Version: Kumquats 1.0\\n" "Report-Msgid-Bugs-To: \\n" "POT-Creation-Date: 2007-07-09 03:39+0100\\n" "PO-Revision-Date: 2001-09-09 01:46+0000\\n" "Last-Translator: L.L. Zamenhoff <*****@*****.**>\\n" "Language-Team: Esperanto <*****@*****.**>\\n" "MIME-Version: 1.0\\n" "Content-Type: text/plain; charset=UTF-8\\n" "Content-Transfer-Encoding: 8bit\\n" # Foo bar. #, c-format #~| msgid "zog" #~ msgid "zig" #~ msgstr "zag" """ ) eo_translation_file = self.parser.parse(pofile_eo) eo_translation_file.is_template = False eo_translation_file.language_code = "eo" eo_translation_file.path = "po/eo.po" eo_translation_file.translation_domain = "testing" eo_translation_file.messages[0].is_obsolete = True storage = ExportFileStorage() self.translation_exporter.exportTranslationFile(eo_translation_file, storage) self._compareImportAndExport(pofile_eo_obsolete.strip(), storage.export().read().strip())
def testObsoleteExport(self): """Check how obsoleted messages are exported.""" pofile_eo = dedent(''' msgid "" msgstr "" "Project-Id-Version: Kumquats 1.0\\n" "Report-Msgid-Bugs-To: \\n" "POT-Creation-Date: 2007-07-09 03:39+0100\\n" "PO-Revision-Date: 2001-09-09 01:46+0000\\n" "Last-Translator: L.L. Zamenhoff <*****@*****.**>\\n" "Language-Team: Esperanto <*****@*****.**>\\n" "MIME-Version: 1.0\\n" "Content-Type: text/plain; charset=UTF-8\\n" "Content-Transfer-Encoding: 8bit\\n" # Foo bar. #, c-format #: src/foo.c #| msgid "zog" msgid "zig" msgstr "zag" ''') pofile_eo_obsolete = dedent(''' msgid "" msgstr "" "Project-Id-Version: Kumquats 1.0\\n" "Report-Msgid-Bugs-To: \\n" "POT-Creation-Date: 2007-07-09 03:39+0100\\n" "PO-Revision-Date: 2001-09-09 01:46+0000\\n" "Last-Translator: L.L. Zamenhoff <*****@*****.**>\\n" "Language-Team: Esperanto <*****@*****.**>\\n" "MIME-Version: 1.0\\n" "Content-Type: text/plain; charset=UTF-8\\n" "Content-Transfer-Encoding: 8bit\\n" # Foo bar. #, c-format #~| msgid "zog" #~ msgid "zig" #~ msgstr "zag" ''') eo_translation_file = self.parser.parse(pofile_eo) eo_translation_file.is_template = False eo_translation_file.language_code = 'eo' eo_translation_file.path = 'po/eo.po' eo_translation_file.translation_domain = 'testing' eo_translation_file.messages[0].is_obsolete = True storage = ExportFileStorage() self.translation_exporter.exportTranslationFile( eo_translation_file, storage) self._compareImportAndExport( pofile_eo_obsolete.strip(), storage.export().read().strip())
def testGeneralExport(self): """Check different kind of messages export.""" pofile_cy = dedent( """ msgid "" msgstr "" "Project-Id-Version: foo\\n" "Report-Msgid-Bugs-To: \\n" "POT-Creation-Date: 2007-07-09 03:39+0100\\n" "PO-Revision-Date: 2001-09-09 01:46+0000\\n" "Last-Translator: Kubla Kahn <*****@*****.**>\\n" "Language-Team: LANGUAGE <*****@*****.**>\\n" "MIME-Version: 1.0\\n" "Content-Type: text/plain; charset=UTF-8\\n" "Content-Transfer-Encoding: 8bit\\n" "Plural-Forms: nplurals=4; plural=n==1 ? 0 : n==2 ? 1 : (n != 8 || n != 11) ? " "2 : 3;\\n" msgid "foo" msgid_plural "foos" msgstr[0] "cy-F001" msgstr[1] "cy-F002" msgstr[2] "" msgstr[3] "" #, fuzzy #| msgid "zog" msgid "zig" msgstr "zag" #, c-format msgid "zip" msgstr "zap" # tove #. borogove #: rath msgid "zog" msgstr "zug" #~ msgid "zot" #~ msgstr "zat" """ ) cy_translation_file = self.parser.parse(pofile_cy) cy_translation_file.is_template = False cy_translation_file.language_code = "cy" cy_translation_file.path = "po/cy.po" cy_translation_file.translation_domain = "testing" storage = ExportFileStorage() self.translation_exporter.exportTranslationFile(cy_translation_file, storage) self._compareImportAndExport(pofile_cy.strip(), storage.export().read().strip())
def testGeneralExport(self): """Check different kind of messages export.""" pofile_cy = dedent(''' msgid "" msgstr "" "Project-Id-Version: foo\\n" "Report-Msgid-Bugs-To: \\n" "POT-Creation-Date: 2007-07-09 03:39+0100\\n" "PO-Revision-Date: 2001-09-09 01:46+0000\\n" "Last-Translator: Kubla Kahn <*****@*****.**>\\n" "Language-Team: LANGUAGE <*****@*****.**>\\n" "MIME-Version: 1.0\\n" "Content-Type: text/plain; charset=UTF-8\\n" "Content-Transfer-Encoding: 8bit\\n" "Plural-Forms: nplurals=4; plural=n==1 ? 0 : n==2 ? 1 : (n != 8 || n != 11) ? " "2 : 3;\\n" msgid "foo" msgid_plural "foos" msgstr[0] "cy-F001" msgstr[1] "cy-F002" msgstr[2] "" msgstr[3] "" #, fuzzy #| msgid "zog" msgid "zig" msgstr "zag" #, c-format msgid "zip" msgstr "zap" # tove #. borogove #: rath msgid "zog" msgstr "zug" #~ msgid "zot" #~ msgstr "zat" ''') cy_translation_file = self.parser.parse(pofile_cy) cy_translation_file.is_template = False cy_translation_file.language_code = 'cy' cy_translation_file.path = 'po/cy.po' cy_translation_file.translation_domain = 'testing' storage = ExportFileStorage() self.translation_exporter.exportTranslationFile( cy_translation_file, storage) self._compareImportAndExport( pofile_cy.strip(), storage.export().read().strip())
def testTarball(self): """Test export of tarball.""" mime = 'application/x-po' storage = ExportFileStorage() storage.addFile('/tmp/a/test/file.po', 'po', 'test file', mime) storage.addFile('/tmp/another/test.po', 'po', 'another test file', mime) outfile = storage.export() tarball = TarFile.open(mode='r|gz', fileobj=StringIO(outfile.read())) elements = set(tarball.getnames()) self.assertTrue('/tmp/a/test/file.po' in elements) self.assertTrue('/tmp/another/test.po' in elements)
def testTarball(self): """Test export of tarball.""" mime = 'application/x-po' storage = ExportFileStorage() storage.addFile('/tmp/a/test/file.po', 'po', 'test file', mime) storage.addFile( '/tmp/another/test.po', 'po', 'another test file', mime) outfile = storage.export() tarball = TarFile.open(mode='r|gz', fileobj=StringIO(outfile.read())) elements = set(tarball.getnames()) self.assertTrue('/tmp/a/test/file.po' in elements) self.assertTrue('/tmp/another/test.po' in elements)
def _testBrokenEncoding(self, pofile_content): translation_file = self.parser.parse(pofile_content % {"charset": "ISO-8859-15", "special": "\xe1"}) translation_file.is_template = False translation_file.language_code = "es" translation_file.path = "po/es.po" translation_file.translation_domain = "testing" # Force the export as ASCII, it will not be possible because # translation is not available in that encoding and thus, we should # get an export in UTF-8. translation_file.header.charset = "ASCII" storage = ExportFileStorage() self.translation_exporter.exportTranslationFile(translation_file, storage) self._compareImportAndExport( pofile_content.strip() % {"charset": "UTF-8", "special": "\xc3\xa1"}, storage.export().read().strip() )
def test_export_template_stays_pot(self): # The MO exporter exports templates in their original POT # format. file_data = self._makeTranslationFileData(is_template=True) storage = ExportFileStorage() GettextMOExporter().exportTranslationFile(file_data, storage) output = storage.export() self.assertEqual('application/x-po', output.content_type) self.assertTrue(output.path.endswith('.pot')) text = output.read() self.assertIn('POT-Creation-Date:', text) self.assertIn('MIME-Version:', text) self.assertIn('msgid', text) self.assertIn('"foo"', text)
def exportTranslationFile(self, translation_file, storage, ignore_obsolete=False, force_utf8=False): """See `ITranslationFormatExporter`.""" translation_exporter = getUtility(ITranslationExporter) gettext_po_exporter = ( translation_exporter.getExporterProducingTargetFileFormat( TranslationFileFormat.PO)) # To generate MO files we need first its PO version and then, # generate the MO one. temp_storage = ExportFileStorage() gettext_po_exporter.exportTranslationFile( translation_file, temp_storage, ignore_obsolete=ignore_obsolete, force_utf8=force_utf8) po_export = temp_storage.export() exported_file_content = po_export.read() if translation_file.is_template: # This exporter is not able to handle template files. We # include those as .pot files stored in a templates/ # directory. file_path = 'templates/%s' % os.path.basename(po_export.path) content_type = gettext_po_exporter.mime_type file_extension = po_export.file_extension else: file_extension = 'mo' # Standard layout for MO files is # 'LANG_CODE/LC_MESSAGES/TRANSLATION_DOMAIN.mo' file_path = os.path.join( translation_file.language_code, 'LC_MESSAGES', '%s.%s' % (translation_file.translation_domain, file_extension)) mo_compiler = POCompiler() mo_content = mo_compiler.compile(exported_file_content) exported_file_content = mo_content content_type = self.mime_type storage.addFile(file_path, file_extension, exported_file_content, content_type)
def _testBrokenEncoding(self, pofile_content): translation_file = self.parser.parse( pofile_content % {'charset': 'ISO-8859-15', 'special': '\xe1'}) translation_file.is_template = False translation_file.language_code = 'es' translation_file.path = 'po/es.po' translation_file.translation_domain = 'testing' # Force the export as ASCII, it will not be possible because # translation is not available in that encoding and thus, we should # get an export in UTF-8. translation_file.header.charset = 'ASCII' storage = ExportFileStorage() self.translation_exporter.exportTranslationFile( translation_file, storage) self._compareImportAndExport( pofile_content.strip() % { 'charset': 'UTF-8', 'special': '\xc3\xa1'}, storage.export().read().strip())
def compare(self, pofile): "Compare the original text with the exported one." "" # This is the word 'Japanese' in Japanese, in Unicode. nihongo_unicode = u"\u65e5\u672c\u8a9e" translation_file = self.parser.parse(pofile) translation_file.is_template = False translation_file.language_code = "ja" translation_file.path = "po/ja.po" translation_file.translation_domain = "testing" # We are sure that 'Japanese' is correctly stored as Unicode so # we are sure the exporter does its job instead of just export # what was imported. self.assertEqual(translation_file.messages[0].translations, [nihongo_unicode]) storage = ExportFileStorage() self.translation_exporter.exportTranslationFile(translation_file, storage) self._compareImportAndExport(pofile.strip(), storage.export().read().strip())
def test_export_MO_produces_MO(self): # Exporting a translation in MO format produces a proper MO # file. file_data = self._makeTranslationFileData(is_template=False) storage = ExportFileStorage() GettextMOExporter().exportTranslationFile(file_data, storage) output = storage.export() self.assertEqual('application/x-gmo', output.content_type) # The file can even be converted back to PO format. retval, text, stderr = run_command( '/usr/bin/msgunfmt', args=['-'], input=output.read()) self.assertEqual(0, retval) self.assertIn('MIME-Version', text) self.assertIn('msgid', text) self.assertIn('"foo"', text)
def compare(self, pofile): "Compare the original text with the exported one.""" # This is the word 'Japanese' in Japanese, in Unicode. nihongo_unicode = u'\u65e5\u672c\u8a9e' translation_file = self.parser.parse(pofile) translation_file.is_template = False translation_file.language_code = 'ja' translation_file.path = 'po/ja.po' translation_file.translation_domain = 'testing' # We are sure that 'Japanese' is correctly stored as Unicode so # we are sure the exporter does its job instead of just export # what was imported. self.assertEqual( translation_file.messages[0].translations, [nihongo_unicode]) storage = ExportFileStorage() self.translation_exporter.exportTranslationFile( translation_file, storage) self._compareImportAndExport( pofile.strip(), storage.export().read().strip())
def exportTranslationFile(self, translation_file, storage, ignore_obsolete=False, force_utf8=False): """See `ITranslationFormatExporter`.""" translation_exporter = getUtility(ITranslationExporter) gettext_po_exporter = translation_exporter.getExporterProducingTargetFileFormat(TranslationFileFormat.PO) # To generate MO files we need first its PO version and then, # generate the MO one. temp_storage = ExportFileStorage() gettext_po_exporter.exportTranslationFile( translation_file, temp_storage, ignore_obsolete=ignore_obsolete, force_utf8=force_utf8 ) po_export = temp_storage.export() exported_file_content = po_export.read() if translation_file.is_template: # This exporter is not able to handle template files. We # include those as .pot files stored in a templates/ # directory. file_path = "templates/%s" % os.path.basename(po_export.path) content_type = gettext_po_exporter.mime_type file_extension = po_export.file_extension else: file_extension = "mo" # Standard layout for MO files is # 'LANG_CODE/LC_MESSAGES/TRANSLATION_DOMAIN.mo' file_path = os.path.join( translation_file.language_code, "LC_MESSAGES", "%s.%s" % (translation_file.translation_domain, file_extension), ) mo_compiler = POCompiler() mo_content = mo_compiler.compile(exported_file_content) exported_file_content = mo_content content_type = self.mime_type storage.addFile(file_path, file_extension, exported_file_content, content_type)
def test_XPITemplateExport(self): """Check a standard export from an XPI file.""" # Prepare the import queue to handle a new .xpi import. self.setUpTranslationImportQueueForTemplate() translation_file_data = getAdapter(self.firefox_template, ITranslationFileData, 'all_messages') storage = ExportFileStorage() self.translation_exporter.exportTranslationFile( translation_file_data, storage) expected_template = dedent(ur''' #, fuzzy msgid "" msgstr "" "<?xml version=\"1.0\"?>\n" "<RDF xmlns=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n" " xmlns:em=\"http://www.mozilla.org/2004/em-rdf#\">\n" " <Description about=\"urn:mozilla:install-manifest\"\n" " em:id=\"[email protected]\"\n" " em:name=\"English U.S. (en-US) Language Pack\"\n" " em:version=\"2.0\"\n" " em:type=\"8\"\n" " em:creator=\"Danilo \u0160egan\">\n" " <em:contributor>\u0414\u0430\u043d\u0438\u043b\u043e \u0428\u0435\u0433\u0430\u043d</em:contributor>\n" " <em:contributor>Carlos Perell\u00f3 Mar\u00edn " "<[email protected]></em:contributor>\n" "\n" " <em:targetApplication>\n" " <Description>\n" " <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id><!-- firefox --" ">\n" " <em:minVersion>2.0</em:minVersion>\n" " <em:maxVersion>2.0.0.*</em:maxVersion>\n" " </Description>\n" " </em:targetApplication>\n" " </Description>\n" "</RDF>\n" #. This is a DTD file inside a subdirectory #: jar:chrome/en-US.jar!/subdir/test2.dtd(foozilla.menu.title) msgctxt "main/subdir/test2.dtd" msgid "MENU" msgstr "" #. Select the access key that you want to use. These have #. to be translated in a way that the selected character is #. present in the translated string of the label being #. referred to, for example 'i' in 'Edit' menu item in #. English. If a translation already exists, please don't #. change it if you are not sure about it. Please find the #. context of the key from the end of the 'Located in' text #. below. #: jar:chrome/en-US.jar!/subdir/test2.dtd(foozilla.menu.accesskey) msgctxt "main/subdir/test2.dtd" msgid "M" msgstr "" #. Select the shortcut key that you want to use. It #. should be translated, but often shortcut keys (for #. example Ctrl + KEY) are not changed from the original. If #. a translation already exists, please don't change it if #. you are not sure about it. Please find the context of #. the key from the end of the 'Located in' text below. #: jar:chrome/en-US.jar!/subdir/test2.dtd(foozilla.menu.commandkey) msgctxt "main/subdir/test2.dtd" msgid "m" msgstr "" #. Translators, what you are seeing now is a lovely, #. awesome, multiline comment aimed at you directly #. from the streets of a .properties file #: jar:chrome/en-US.jar!/subdir/test2.properties:6(foozilla_something) msgctxt "main/subdir/test2.properties" msgid "SomeZilla" msgstr "" #: jar:chrome/en-US.jar!/test1.dtd(foozilla.name) msgctxt "main/test1.dtd" msgid "FooZilla!" msgstr "" #. Translators, don't play with fire! #: jar:chrome/en-US.jar!/test1.dtd(foozilla.play.fire) msgctxt "main/test1.dtd" msgid "Do you want to play with fire?" msgstr "" #. This is just a comment, not a comment for translators #: jar:chrome/en-US.jar!/test1.dtd(foozilla.play.ice) msgctxt "main/test1.dtd" msgid "Play with ice?" msgstr "" #: jar:chrome/en-US.jar!/test1.properties:1(foozilla.title) msgctxt "main/test1.properties" msgid "FooZilla Zilla Thingy" msgstr "" #. Translators, if you're older than six, don't translate this #: jar:chrome/en-US.jar!/test1.properties:3(foozilla.happytitle) msgctxt "main/test1.properties" msgid "http://foozillingy.happy.net/" msgstr "" #. (Except this one) #: jar:chrome/en-US.jar!/test1.properties:4(foozilla.nocomment) msgctxt "main/test1.properties" msgid "No Comment" msgstr "" #: jar:chrome/en-US.jar!/test1.properties:5(foozilla.utf8) msgctxt "main/test1.properties" msgid "\u0414\u0430\u043d=Day" msgstr "" ''').strip() output = storage.export().read().decode("utf-8") self._compareExpectedAndExported(expected_template, output)
def test_XPITemplateExport(self): """Check a standard export from an XPI file.""" # Prepare the import queue to handle a new .xpi import. self.setUpTranslationImportQueueForTemplate() translation_file_data = getAdapter( self.firefox_template, ITranslationFileData, 'all_messages') storage = ExportFileStorage() self.translation_exporter.exportTranslationFile( translation_file_data, storage) expected_template = dedent(ur''' #, fuzzy msgid "" msgstr "" "<?xml version=\"1.0\"?>\n" "<RDF xmlns=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n" " xmlns:em=\"http://www.mozilla.org/2004/em-rdf#\">\n" " <Description about=\"urn:mozilla:install-manifest\"\n" " em:id=\"[email protected]\"\n" " em:name=\"English U.S. (en-US) Language Pack\"\n" " em:version=\"2.0\"\n" " em:type=\"8\"\n" " em:creator=\"Danilo \u0160egan\">\n" " <em:contributor>\u0414\u0430\u043d\u0438\u043b\u043e \u0428\u0435\u0433\u0430\u043d</em:contributor>\n" " <em:contributor>Carlos Perell\u00f3 Mar\u00edn " "<[email protected]></em:contributor>\n" "\n" " <em:targetApplication>\n" " <Description>\n" " <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id><!-- firefox --" ">\n" " <em:minVersion>2.0</em:minVersion>\n" " <em:maxVersion>2.0.0.*</em:maxVersion>\n" " </Description>\n" " </em:targetApplication>\n" " </Description>\n" "</RDF>\n" #. This is a DTD file inside a subdirectory #: jar:chrome/en-US.jar!/subdir/test2.dtd(foozilla.menu.title) msgctxt "main/subdir/test2.dtd" msgid "MENU" msgstr "" #. Select the access key that you want to use. These have #. to be translated in a way that the selected character is #. present in the translated string of the label being #. referred to, for example 'i' in 'Edit' menu item in #. English. If a translation already exists, please don't #. change it if you are not sure about it. Please find the #. context of the key from the end of the 'Located in' text #. below. #: jar:chrome/en-US.jar!/subdir/test2.dtd(foozilla.menu.accesskey) msgctxt "main/subdir/test2.dtd" msgid "M" msgstr "" #. Select the shortcut key that you want to use. It #. should be translated, but often shortcut keys (for #. example Ctrl + KEY) are not changed from the original. If #. a translation already exists, please don't change it if #. you are not sure about it. Please find the context of #. the key from the end of the 'Located in' text below. #: jar:chrome/en-US.jar!/subdir/test2.dtd(foozilla.menu.commandkey) msgctxt "main/subdir/test2.dtd" msgid "m" msgstr "" #. Translators, what you are seeing now is a lovely, #. awesome, multiline comment aimed at you directly #. from the streets of a .properties file #: jar:chrome/en-US.jar!/subdir/test2.properties:6(foozilla_something) msgctxt "main/subdir/test2.properties" msgid "SomeZilla" msgstr "" #: jar:chrome/en-US.jar!/test1.dtd(foozilla.name) msgctxt "main/test1.dtd" msgid "FooZilla!" msgstr "" #. Translators, don't play with fire! #: jar:chrome/en-US.jar!/test1.dtd(foozilla.play.fire) msgctxt "main/test1.dtd" msgid "Do you want to play with fire?" msgstr "" #. This is just a comment, not a comment for translators #: jar:chrome/en-US.jar!/test1.dtd(foozilla.play.ice) msgctxt "main/test1.dtd" msgid "Play with ice?" msgstr "" #: jar:chrome/en-US.jar!/test1.properties:1(foozilla.title) msgctxt "main/test1.properties" msgid "FooZilla Zilla Thingy" msgstr "" #. Translators, if you're older than six, don't translate this #: jar:chrome/en-US.jar!/test1.properties:3(foozilla.happytitle) msgctxt "main/test1.properties" msgid "http://foozillingy.happy.net/" msgstr "" #. (Except this one) #: jar:chrome/en-US.jar!/test1.properties:4(foozilla.nocomment) msgctxt "main/test1.properties" msgid "No Comment" msgstr "" #: jar:chrome/en-US.jar!/test1.properties:5(foozilla.utf8) msgctxt "main/test1.properties" msgid "\u0414\u0430\u043d=Day" msgstr "" ''').strip() output = storage.export().read().decode("utf-8") self._compareExpectedAndExported(expected_template, output)