def test_write(): """Test writing a basic catalog. """ catalog = Catalog() catalog.add('green', context='colors:0') catalog.add('red', context='colors:1') assert po2xml(catalog) == {'colors': ['green', 'red']}
def test_write_incomplete_plural(): """Test behaviour with incompletely translated plurals in .po.""" catalog = Catalog() catalog.language = Language('bs') # Bosnian catalog.add(('foo', 'foos'), ('one', '', 'many', ''), context='foo') assert po2xml(catalog) == {'foo': { 'few': '', 'many': 'many', 'other': '', 'one': 'one'}}
def test_no_wrap_and_width_behaviour_on_comments(self): catalog = Catalog() catalog.add("Pretty dam long message id, which must really be big " "to test this wrap behaviour, if not it won't work.", locations=[("fake.py", n) for n in range(1, 30)]) buf = BytesIO() pofile.write_po(buf, catalog, width=None, omit_header=True) self.assertEqual(b"""\ #: fake.py:1 fake.py:2 fake.py:3 fake.py:4 fake.py:5 fake.py:6 fake.py:7 #: fake.py:8 fake.py:9 fake.py:10 fake.py:11 fake.py:12 fake.py:13 fake.py:14 #: fake.py:15 fake.py:16 fake.py:17 fake.py:18 fake.py:19 fake.py:20 fake.py:21 #: fake.py:22 fake.py:23 fake.py:24 fake.py:25 fake.py:26 fake.py:27 fake.py:28 #: fake.py:29 msgid "pretty dam long message id, which must really be big to test this wrap behaviour, if not it won't work." msgstr "" """, buf.getvalue().lower()) buf = BytesIO() pofile.write_po(buf, catalog, width=100, omit_header=True) self.assertEqual(b"""\ #: fake.py:1 fake.py:2 fake.py:3 fake.py:4 fake.py:5 fake.py:6 fake.py:7 fake.py:8 fake.py:9 fake.py:10 #: fake.py:11 fake.py:12 fake.py:13 fake.py:14 fake.py:15 fake.py:16 fake.py:17 fake.py:18 fake.py:19 #: fake.py:20 fake.py:21 fake.py:22 fake.py:23 fake.py:24 fake.py:25 fake.py:26 fake.py:27 fake.py:28 #: fake.py:29 msgid "" "pretty dam long message id, which must really be big to test this wrap behaviour, if not it won't" " work." msgstr "" """, buf.getvalue().lower())
def run(self): mappings = self._get_mappings() with open(self.output_file, 'wb') as outfile: catalog = Catalog(project=self.project, version=self.version, msgid_bugs_address=self.msgid_bugs_address, copyright_holder=self.copyright_holder, charset=self.charset) for path, method_map, options_map in mappings: def callback(filename, method, options): if method == 'ignore': return # If we explicitly provide a full filepath, just use that. # Otherwise, path will be the directory path and filename # is the relative path from that dir to the file. # So we can join those to get the full filepath. if os.path.isfile(path): filepath = path else: filepath = os.path.normpath(os.path.join(path, filename)) optstr = '' if options: optstr = ' (%s)' % ', '.join(['%s="%s"' % (k, v) for k, v in options.items()]) self.log.info('extracting messages from %s%s', filepath, optstr) if os.path.isfile(path): current_dir = os.getcwd() extracted = check_and_call_extract_file( path, method_map, options_map, callback, self.keywords, self.add_comments, self.strip_comments, current_dir ) else: extracted = extract_from_dir( path, method_map, options_map, keywords=self.keywords, comment_tags=self.add_comments, callback=callback, strip_comment_tags=self.strip_comments ) for fname, lineno, msg, comments, context, flags in extracted: if os.path.isfile(path): filepath = fname # already normalized else: filepath = os.path.normpath(os.path.join(path, fname)) catalog.add(msg, None, [(filepath, lineno)], flags=flags, auto_comments=comments, context=context) self.log.info('writing PO template file to %s', self.output_file) write_po(outfile, catalog, width=self.width, no_location=self.no_location, omit_header=self.omit_header, sort_output=self.sort_output, sort_by_file=self.sort_by_file, include_lineno=self.include_lineno)
def test_po_with_multiline_obsolete_message(self): catalog = Catalog() catalog.add(u'foo', u'Voh', locations=[('main.py', 1)]) msgid = r"""Here's a message that covers multiple lines, and should still be handled correctly. """ msgstr = r"""Here's a message that covers multiple lines, and should still be handled correctly. """ catalog.obsolete[msgid] = Message(msgid, msgstr, locations=[('utils.py', 3)]) buf = BytesIO() pofile.write_po(buf, catalog, omit_header=True) self.assertEqual(b'''#: main.py:1 msgid "foo" msgstr "Voh" #~ msgid "" #~ "Here's a message that covers\\n" #~ "multiple lines, and should still be handled\\n" #~ "correctly.\\n" #~ msgstr "" #~ "Here's a message that covers\\n" #~ "multiple lines, and should still be handled\\n" #~ "correctly.\\n"''', buf.getvalue().strip())
def handle(self, *args, **options): if args: # mimics puente.management.commands.extract for a list of files outputdir = os.path.join(settings.ROOT, 'locale', 'templates', 'LC_MESSAGES') if not os.path.isdir(outputdir): os.makedirs(outputdir) catalog = Catalog( header_comment='', project=get_setting('PROJECT'), version=get_setting('VERSION'), msgid_bugs_address=get_setting('MSGID_BUGS_ADDRESS'), charset='utf-8', ) for filename, lineno, msg, cmts, ctxt in extract_from_files(args): catalog.add(msg, None, [(filename, lineno)], auto_comments=cmts, context=ctxt) with open(os.path.join(outputdir, '%s.pot' % DOMAIN), 'wb') as fp: write_po(fp, catalog, width=80) else: # This is basically a wrapper around the puente extract # command, we might want to do some things around this in the # future gettext_extract() pot_to_langfiles(DOMAIN)
def test_write_po_file_with_specified_charset(self): catalog = Catalog(charset="iso-8859-1") catalog.add("foo", "\xe4\xf6\xfc", locations=[("main.py", 1)]) buf = BytesIO() pofile.write_po(buf, catalog, omit_header=False) po_file = buf.getvalue().strip() assert br'"Content-Type: text/plain; charset=iso-8859-1\n"' in po_file assert 'msgstr "\xe4\xf6\xfc"'.encode("iso-8859-1") in po_file
def test_write_po_file_with_specified_charset(self): catalog = Catalog(charset='iso-8859-1') catalog.add('foo', u'äöü', locations=[('main.py', 1)]) buf = BytesIO() pofile.write_po(buf, catalog, omit_header=False) po_file = buf.getvalue().strip() assert b'"Content-Type: text/plain; charset=iso-8859-1\\n"' in po_file assert u'msgstr "äöü"'.encode('iso-8859-1') in po_file
def test_write_missing_translations(): """[Regression] Specifically test that arrays are not written to the XML in an incomplete fashion if parts of the array are not translated. """ catalog = Catalog() catalog.add('green', context='colors:0') # does not have a translation catalog.add('red', 'rot', context='colors:1') assert po2xml(catalog) == {'colors': ['green', 'rot']}
def test_write(): """Test writing a basic catalog. """ catalog = Catalog() catalog.add('green', context='colors:0') catalog.add('red', context='colors:1') assert etree.tostring(po2xml(catalog, with_untranslated=True)) == \ '<resources><string-array name="colors"><item>green</item><item>red</item></string-array></resources>'
def test_file_sorted_po(self): catalog = Catalog() catalog.add(u'bar', locations=[('utils.py', 3)]) catalog.add((u'foo', u'foos'), (u'Voh', u'Voeh'), locations=[('main.py', 1)]) buf = BytesIO() pofile.write_po(buf, catalog, sort_by_file=True) value = buf.getvalue().strip() assert value.find(b'main.py') < value.find(b'utils.py')
def test_message_invalid_parameter_syntax(self): en_catalog = Catalog() en_catalog.add("id", string="Hello {a} {b}") el_catalog = Catalog() el_catalog.add("id", string="Hey {a b}!") with mock_app_catalogs({"el": el_catalog, "en": en_catalog}): with self.assertLogs(level=logging.ERROR): result = localize("el", "id", arguments={"a": "you", "b": "!"}) self.assertEqual(result, "Hello you !")
def test_no_include_lineno(self): catalog = Catalog() catalog.add(u'foo', locations=[('main.py', 1)]) catalog.add(u'foo', locations=[('utils.py', 3)]) buf = BytesIO() pofile.write_po(buf, catalog, omit_header=True, include_lineno=False) self.assertEqual(b'''#: main.py utils.py msgid "foo" msgstr ""''', buf.getvalue().strip())
def test_join_locations(self): catalog = Catalog() catalog.add(u'foo', locations=[('main.py', 1)]) catalog.add(u'foo', locations=[('utils.py', 3)]) buf = BytesIO() pofile.write_po(buf, catalog, omit_header=True) self.assertEqual(b'''#: main.py:1 utils.py:3 msgid "foo" msgstr ""''', buf.getvalue().strip())
def test_find_corresponding_message_with_context_not_exists(self): catalog = Catalog() catalog.add("id", string="Text") corresponding = find_corresponding_message( catalog, Message("id", context="ctxt")) self.assertIsNone(corresponding) self.assertIsNone( find_corresponding_string(catalog, Message("other id", context="ctxt")))
def test_move_strings_to_comments(self): catalog = Catalog() catalog.add("id", string="Text1") move_strings_to_comments(catalog, comment_tag="default-message") expected = Catalog() expected.add("id", string="", auto_comments=["default-message: Text1"]) assert_catalogs_deeply_equal(catalog, expected)
def test_duplicate_comments(self): catalog = Catalog() catalog.add(u'foo', auto_comments=['A comment']) catalog.add(u'foo', auto_comments=['A comment']) buf = BytesIO() pofile.write_po(buf, catalog, omit_header=True) self.assertEqual(b'''#. A comment msgid "foo" msgstr ""''', buf.getvalue().strip())
def test_trans_noop(self): catalog = Catalog() catalog.add("id", string="Hello {a} {b}!") with mock_app_catalogs({"en": catalog}): self.assertIsNone( trans_html(mock_context(), "id", noop=True, default="Hello {a} {b}!"))
def test_message_invalid_parameter_syntax(self): catalog = Catalog() catalog.add("id", string="Hey {a b}!") with self.assertRaises(ICUError): result = MessageTranslator("en", catalog).get_and_format_message( "id", arguments={ "a": "you", "b": "!" })
def test_find_fuzzy_messages_ignore_empty_old(self): old_catalog = Catalog() old_catalog.add("id1", string="") new_catalog = Catalog() old_catalog.add("id1", string="Text1") self.assertEqual( find_fuzzy_messages(old_catalog=old_catalog, new_catalog=new_catalog), frozenset(), )
def test_find_fuzzy_messages_fuzzy_with_context(self): old_catalog = Catalog() old_catalog.add("id1", string="Text1", context="ctxt") new_catalog = Catalog() new_catalog.add("id1", string="Text1new", context="ctxt") self.assertEqual( find_fuzzy_messages(old_catalog=old_catalog, new_catalog=new_catalog), frozenset([("id1", "ctxt")]), )
def test_write(): """Test writing a basic catalog. """ catalog = Catalog() catalog.add("green", context="colors:0") catalog.add("red", context="colors:1") assert ( etree.tostring(po2xml(catalog, with_untranslated=True)) == '<resources><string-array name="colors"><item>green</item><item>red</item></string-array></resources>' )
def test_po_with_previous_msgid(self): catalog = Catalog() catalog.add(u'foo', u'Voh', locations=[('main.py', 1)], previous_id=u'fo') buf = BytesIO() pofile.write_po(buf, catalog, omit_header=True, include_previous=True) self.assertEqual(b'''#: main.py:1 #| msgid "fo" msgid "foo" msgstr "Voh"''', buf.getvalue().strip())
def test_find_fuzzy_messages_fuzzy(self): old_catalog = Catalog() old_catalog.add("id1", string="Text1") new_catalog = Catalog() new_catalog.add("id1", string="Text1new") self.assertEqual( find_fuzzy_messages(old_catalog=old_catalog, new_catalog=new_catalog), frozenset(["id1"]), )
def test_find_fuzzy_messages_ignore_already_fuzzy(self): old_catalog = Catalog() old_catalog.add("id1", string="Text1", flags=["fuzzy"]) new_catalog = Catalog() new_catalog.add("id1", string="Text1", flags=["fuzzy"]) self.assertEqual( find_fuzzy_messages(old_catalog=old_catalog, new_catalog=new_catalog), frozenset(), )
def test_add_or_update_message_update(self): target_catalog = Catalog() target_catalog.add("id1", string="Text1") add_or_update_message(target_catalog, Message("id1", string="Text2")) expected_catalog = Catalog() expected_catalog.add("id1", string="Text2") assert_catalogs_deeply_equal(target_catalog, expected_catalog)
def test_write(): """Test a basic po2xml() call. (what the import command does). """ catalog = Catalog() catalog.language = Language('bs') # Bosnian catalog.add(('foo', 'foos'), ('few', 'many', 'one', 'other'), context='foo') assert po2xml(catalog) == {'foo': { 'few': 'few', 'many': 'many', 'one': 'one', 'other': 'other'}}
def test_copy_catalog_replaces_messages(self): old_catalog = Catalog() old_catalog.add("id", string="Text1") # Copy catalog new_catalog = copy_catalog(old_catalog) # And then change strings in the old catalog for message in old_catalog: message.string = "Text2" # Copy should be unaffected self.assertEqual(new_catalog.get("id").string, "Text1")
def po_catalog_export(self): """ Export a catalog from a project into a PO file """ toast_path = "/home/django/Emencia/po_headquarter/dummy_po/" project = Project.objects.get(slug='dummy') catalog = Catalog.objects.get(project=project, locale='fr') #mime_dict = json.loads(catalog.mime_headers) forged_catalog = BabelCatalog(locale=catalog.locale, header_comment=catalog.header_comment, project=project.name, version="0.2.0") print("before add:", len(forged_catalog)) for entry in catalog.translationmsg_set.all().order_by('id'): locations = [ tuple(item) for item in json.loads(entry.template.locations) ] forged_catalog.add(entry.template.message, string=entry.message, locations=locations, flags=entry.template.flags) print("after add:", len(forged_catalog)) print("errors:", [item for item in forged_catalog.check()]) print() print("---------------- Original") fpw = StringIO() write_po(fpw, forged_catalog, sort_by_file=False, ignore_obsolete=True, include_previous=False) print(fpw.getvalue()) fpw.close() print() print("---------------- Updated") fp3 = open(os.path.join(toast_path, '0-3-0.pot'), 'r') template_catalog_3 = read_po(fp3) forged_catalog.update(template_catalog_3) fpw = StringIO() write_po(fpw, forged_catalog, sort_by_file=False, ignore_obsolete=True, include_previous=False) print(fpw.getvalue()) fpw.close()
def test_gettext_disallow_fuzzy_translations(app): locale_dir = app.srcdir / 'locales' / 'de' / 'LC_MESSAGES' locale_dir.makedirs() with (locale_dir / 'index.po').open('wb') as f: catalog = Catalog() catalog.add('features', 'FEATURES', flags=('fuzzy',)) pofile.write_po(f, catalog) app.build() content = (app.outdir / 'index.html').read_text() assert 'FEATURES' not in content
def test_write_incomplete_plural(): """Test behaviour with incompletely translated plurals in .po.""" catalog = Catalog() catalog.language = Language('bs') # Bosnian catalog.add(('foo', 'foos'), ('one', '', ''), context='foo') assert_equal(po2xml(catalog), {'foo': { 'few': '', 'one': 'one', 'other': '' }})
def _update_piglatin(): from babel.messages.pofile import read_po, write_po from babel.messages.catalog import Catalog with open('app/messages.pot', 'r') as f: template = read_po(f) catalog = Catalog() for message in template: trans = ' '.join([_piglatin_translate(w) for w in message.id.split(' ')]) catalog.add(message.id, trans, locations=message.locations) with open('app/translations/aa/LC_MESSAGES/messages.po', 'w') as f: write_po(f, catalog)
def test_write_skipped_ids(): """Test that arrays were ids are missing are written properly out as well. """ # TODO: Indices missing at the end of the array will not be noticed, # because we are not aware of the arrays full length. # TODO: If we where smart enough to look in the original resource XML, # we could fill in missing array strings with the untranslated value. catalog = Catalog() catalog.add('red', context='colors:3') catalog.add('green', context='colors:1') assert po2xml(catalog) == {'colors': [None, 'green', None, 'red']}
def test_no_html_escape(self): catalog = Catalog() catalog.add( "id", string= 'Hello <a href="/you?a=n&b=e">you > {param_b}</a> my & friend') self.assertEqual( MessageTranslator("en", catalog).get_and_format_message( "id", arguments={"param_b": "> there"}), 'Hello <a href="/you?a=n&b=e">you > > there</a> my & friend', )
def test_find_corresponding_message_with_context_exists(self): catalog = Catalog() catalog.add("id", string="Text", context="ctxt") corresponding = find_corresponding_message( catalog, Message("id", context="ctxt")) self.assertTrue(corresponding) assert_messages_deeply_equal(corresponding, catalog.get("id", context="ctxt")) self.assertEqual( find_corresponding_string(catalog, Message("id", context="ctxt")), "Text")
def create_i18n_files(lang, quiet=True): sql = """ SELECT * FROM translation WHERE lang = ? and active=1; """ result = conn.execute(sql, lang) catalog = Catalog(locale=lang) for row in result: if row.plural: key = (row.id, row.plural) values = [ row.trans1, row.trans2, row.trans3, row.trans4, ] value = [] for v in values: if v: value.append(v) if len(value) == 1: value = value[0] else: value = tuple(value) else: key = row.id value = row.trans1 catalog.add(key, value) path = os.path.join(DIR, 'translations', lang, 'LC_MESSAGES') try: os.makedirs(path) except OSError: pass outfile = open(os.path.join(path, 'messages.po'), 'wb') try: if not quiet: print 'writing PO for', lang write_po(outfile, catalog) finally: outfile.close() outfile = open(os.path.join(path, 'messages.mo'), 'wb') try: if not quiet: print 'writing MO for', lang write_mo(outfile, catalog) finally: outfile.close()
def test_po_with_obsolete_message_ignored(self): catalog = Catalog() catalog.add(u'foo', u'Voh', locations=[('main.py', 1)]) catalog.obsolete['bar'] = Message(u'bar', u'Bahr', locations=[('utils.py', 3)], user_comments=['User comment']) buf = BytesIO() pofile.write_po(buf, catalog, omit_header=True, ignore_obsolete=True) self.assertEqual(b'''#: main.py:1 msgid "foo" msgstr "Voh"''', buf.getvalue().strip())
def _update_english(): from babel.messages.pofile import read_po, write_po from babel.messages.catalog import Catalog with open('app/messages.pot', 'r') as f: template = read_po(f) catalog = Catalog() for message in template: catalog.add(message.id, message.id, locations=message.locations) with open('app/translations/en/LC_MESSAGES/messages.po', 'w') as f: write_po(f, catalog) with open('app/translations/en_US/LC_MESSAGES/messages.po', 'w') as f: write_po(f, catalog)
def test_po_with_obsolete_message_ignored(self): catalog = Catalog() catalog.add("foo", "Voh", locations=[("main.py", 1)]) catalog.obsolete["bar"] = Message("bar", "Bahr", locations=[("utils.py", 3)], user_comments=["User comment"]) buf = BytesIO() pofile.write_po(buf, catalog, omit_header=True, ignore_obsolete=True) self.assertEqual( b'''#: main.py:1 msgid "foo" msgstr "Voh"''', buf.getvalue().strip(), )
def test_message_different_arguments(self): catalog = Catalog() catalog.add("id", string="Hey {a} {0} {c}") self.assertEqual( MessageTranslator("en", catalog).get_and_format_message("id", arguments={ "a": "you", "b": "!" }), "Hey you {0} {c}", )
def test_write_skipped_ids(): """Test that catalogs were ids are missing are written properly out as well. """ # TODO: We currently simply maintain order, but shouldn't we instead # write out missing ids as empty strings? If the source file says # colors:9, that likely means the dev. expects 8 strings before it. catalog = Catalog() catalog.add('red', context='colors:9') catalog.add('green', context='colors:4') assert etree.tostring(po2xml(catalog, with_untranslated=True)) == \ '<resources><string-array name="colors"><item>green</item><item>red</item></string-array></resources>'
def test_write_ignore_untranslated_plural(): """An untranslated plural is not included in the XML. """ catalog = Catalog() catalog.language = Language('en') catalog.add(('foo', 'foos'), context='foo') assert po2xml(catalog) == {} # Even with ``with_untranslated``, we still do not include # empty plural (they would just block access to the untranslated # master version, which we cannot copy into the target). assert po2xml(catalog) == {}
def test_wrap_locations_with_hyphens(self): catalog = Catalog() catalog.add("foo", locations=[("doupy/templates/base/navmenu.inc.html.py", 60)]) catalog.add("foo", locations=[("doupy/templates/job-offers/helpers.html", 22)]) buf = BytesIO() pofile.write_po(buf, catalog, omit_header=True) self.assertEqual( b'''#: doupy/templates/base/navmenu.inc.html.py:60 #: doupy/templates/job-offers/helpers.html:22 msgid "foo" msgstr ""''', buf.getvalue().strip(), )
def run_gettext(dirname, for_js): catalog = Catalog() for filename, lineno, message, comments, context in extract_from_dir( dirname, method_map=[('**.js', 'javascript')] if for_js else [('**.py', 'python')] ): catalog.add(message, None, [(filename, lineno)], auto_comments=comments, context=context) sio = cStringIO.StringIO() write_po(sio, catalog) return sio.getvalue()
def test_po_with_previous_msgid_plural(self): catalog = Catalog() catalog.add((u'foo', u'foos'), (u'Voh', u'Voeh'), locations=[('main.py', 1)], previous_id=(u'fo', u'fos')) buf = StringIO() pofile.write_po(buf, catalog, omit_header=True, include_previous=True) self.assertEqual('''#: main.py:1 #| msgid "fo" #| msgid_plural "fos" msgid "foo" msgid_plural "foos" msgstr[0] "Voh" msgstr[1] "Voeh"''', buf.getvalue().strip())
def fake_extract_command(filename, fileobj, method, options=generate_options_map(), keywords=get_setting('KEYWORDS'), comment_tags=get_setting('COMMENT_TAGS')): catalog = Catalog(charset='utf-8') extracted = fake_extract_from_dir(filename, fileobj, method, options, keywords, comment_tags) for filename, lineno, msg, cmts, ctxt in extracted: catalog.add(msg, None, [(filename, lineno)], auto_comments=cmts, context=ctxt) po_out = StringIO() write_po(po_out, catalog, width=80, omit_header=True) return unicode(po_out.getvalue())
def test_overwrite_po_success(minimal_i18n_settings, temp_builds_dir, fixtures_settings): """ safe_write_po usage for overwritting file """ basepath = temp_builds_dir.join('i18n_overwrite_po_success') # Copy sample project to temporary dir samplename = 'minimal_i18n' samplepath = os.path.join(fixtures_settings.fixtures_path, samplename) destination = os.path.join(basepath.strpath, samplename) shutil.copytree(samplepath, destination) dummy_name = "dummy_pot.pot" dummy_pot = os.path.join(destination, dummy_name) # Get manager with settings settings = minimal_i18n_settings(destination) manager = I18NManager(settings) # Create a dummy catalog to write catalog = Catalog(header_comment="# Foobar") catalog.add('foo %(name)s', locations=[('main.py', 1)], flags=('fuzzy',)) # Write it manager.safe_write_po(catalog, dummy_pot) # Check it with io.open(dummy_pot, 'rb') as f: dummy_catalog = read_po(f) assert dummy_catalog.header_comment == "# Foobar" # New dummy catalog to overwrite previous one catalog = Catalog(header_comment="# Zob") catalog.add('ping', string='pong', locations=[('nope.py', 42)]) # Write it manager.safe_write_po(catalog, dummy_pot) # List existing pot file at root pots = [item for item in os.listdir(destination) if item.endswith('.pot')] # No other pot file assert pots == [dummy_name] # Check it again with io.open(dummy_pot, 'rb') as f: dummy_catalog = read_po(f) assert dummy_catalog.header_comment == "# Zob" assert dummy_catalog["ping"] == Message('ping', string='pong')