def test_catalog(): cat = catalog.Catalog(project='Foobar', version='1.0', copyright_holder='Foo Company') assert cat.header_comment == ('# Translations template for Foobar.\n' '# Copyright (C) %(year)d Foo Company\n' '# This file is distributed under the same ' 'license as the Foobar project.\n' '# FIRST AUTHOR <EMAIL@ADDRESS>, %(year)d.\n' '#') % { 'year': datetime.date.today().year } cat = catalog.Catalog(project='Foobar', version='1.0', copyright_holder='Foo Company') cat.header_comment = ( '# The POT for my really cool PROJECT project.\n' '# Copyright (C) 1990-2003 ORGANIZATION\n' '# This file is distributed under the same license as the PROJECT\n' '# project.\n' '#\n') assert cat.header_comment == ( '# The POT for my really cool Foobar project.\n' '# Copyright (C) 1990-2003 Foo Company\n' '# This file is distributed under the same license as the Foobar\n' '# project.\n' '#\n')
def test_catalog_update(): template = catalog.Catalog() template.add('green', locations=[('main.py', 99)]) template.add('blue', locations=[('main.py', 100)]) template.add(('salad', 'salads'), locations=[('util.py', 42)]) cat = catalog.Catalog(locale='de_DE') cat.add('blue', u'blau', locations=[('main.py', 98)]) cat.add('head', u'Kopf', locations=[('util.py', 33)]) cat.add(('salad', 'salads'), (u'Salat', u'Salate'), locations=[('util.py', 38)]) cat.update(template) assert len(cat) == 3 msg1 = cat['green'] msg1.string assert msg1.locations == [('main.py', 99)] msg2 = cat['blue'] assert msg2.string == u'blau' assert msg2.locations == [('main.py', 100)] msg3 = cat['salad'] assert msg3.string == (u'Salat', u'Salate') assert msg3.locations == [('util.py', 42)] assert not 'head' in cat assert list(cat.obsolete.values())[0].id == 'head'
def test_catalog_update(): template = catalog.Catalog(header_comment="# A Custom Header") template.add('green', locations=[('main.py', 99)]) template.add('blue', locations=[('main.py', 100)]) template.add(('salad', 'salads'), locations=[('util.py', 42)]) cat = catalog.Catalog(locale='de_DE') cat.add('blue', u'blau', locations=[('main.py', 98)]) cat.add('head', u'Kopf', locations=[('util.py', 33)]) cat.add(('salad', 'salads'), (u'Salat', u'Salate'), locations=[('util.py', 38)]) cat.update(template) assert len(cat) == 3 msg1 = cat['green'] msg1.string assert msg1.locations == [('main.py', 99)] msg2 = cat['blue'] assert msg2.string == u'blau' assert msg2.locations == [('main.py', 100)] msg3 = cat['salad'] assert msg3.string == (u'Salat', u'Salate') assert msg3.locations == [('util.py', 42)] assert 'head' not in cat assert list(cat.obsolete.values())[0].id == 'head' cat.update(template, update_header_comment=True) assert cat.header_comment == template.header_comment # Header comment also gets updated
def test_update_message_changed_to_simple(self): cat = catalog.Catalog() cat.add(('foofoos'), ('Voh', 'V\xf6hs')) tmpl = catalog.Catalog() tmpl.add('foo') cat.update(tmpl) self.assertEqual('Voh', cat['foo'].string) assert cat['foo'].fuzzy
def test_update_without_fuzzy_matching(self): cat = catalog.Catalog() cat.add('fo', 'Voh') cat.add('bar', 'Bahr') tmpl = catalog.Catalog() tmpl.add('foo') cat.update(tmpl, no_fuzzy_matching=True) self.assertEqual(2, len(cat.obsolete))
def test_update_message_changed_to_simple(self): cat = catalog.Catalog() cat.add(u'foo' u'foos', (u'Voh', u'Vöhs')) tmpl = catalog.Catalog() tmpl.add(u'foo') cat.update(tmpl) self.assertEqual(u'Voh', cat['foo'].string) assert cat['foo'].fuzzy
def test_update_message_changed_to_plural(self): cat = catalog.Catalog() cat.add(u'foo', u'Voh') tmpl = catalog.Catalog() tmpl.add((u'foo', u'foos')) cat.update(tmpl) self.assertEqual((u'Voh', ''), cat['foo'].string) assert cat['foo'].fuzzy
def test_catalog_setitem(): cat = catalog.Catalog() cat[u'foo'] = catalog.Message(u'foo') assert cat[u'foo'].id == 'foo' cat = catalog.Catalog() cat[u'foo'] = catalog.Message(u'foo', locations=[('main.py', 1)]) assert cat[u'foo'].locations == [('main.py', 1)] cat[u'foo'] = catalog.Message(u'foo', locations=[('utils.py', 5)]) assert cat[u'foo'].locations == [('main.py', 1), ('utils.py', 5)]
def test_update_no_template_mutation(self): tmpl = catalog.Catalog() tmpl.add('foo') cat1 = catalog.Catalog() cat1.add('foo', 'Voh') cat1.update(tmpl) cat2 = catalog.Catalog() cat2.update(tmpl) self.assertEqual(None, cat2['foo'].string) self.assertEqual(False, cat2['foo'].fuzzy)
def test_update_fuzzy_matching_with_char_change(self): cat = catalog.Catalog() cat.add('fo', 'Voh') cat.add('bar', 'Bahr') tmpl = catalog.Catalog() tmpl.add('foo') cat.update(tmpl) self.assertEqual(1, len(cat.obsolete)) assert 'fo' not in cat self.assertEqual('Voh', cat['foo'].string) self.assertEqual(True, cat['foo'].fuzzy)
def test_update_fuzzy_matching_with_new_context(self): cat = catalog.Catalog() cat.add('foo', 'Voh') cat.add('bar', 'Bahr') tmpl = catalog.Catalog() tmpl.add('Foo', context='Menu') cat.update(tmpl) self.assertEqual(1, len(cat.obsolete)) assert 'foo' not in cat message = cat.get('Foo', 'Menu') self.assertEqual('Voh', message.string) self.assertEqual(True, message.fuzzy) self.assertEqual('Menu', message.context)
def test_update_fuzzy_matching_no_msgstr(self): cat = catalog.Catalog() cat.add('fo', '') tmpl = catalog.Catalog() tmpl.add('fo') tmpl.add('foo') cat.update(tmpl) assert 'fo' in cat assert 'foo' in cat self.assertEqual('', cat['fo'].string) self.assertEqual(False, cat['fo'].fuzzy) self.assertEqual(None, cat['foo'].string) self.assertEqual(False, cat['foo'].fuzzy)
def test_update_fuzzy_matching_with_changed_context(self): cat = catalog.Catalog() cat.add('foo', 'Voh', context='Menu|File') cat.add('bar', 'Bahr', context='Menu|File') tmpl = catalog.Catalog() tmpl.add('Foo', context='Menu|Edit') cat.update(tmpl) self.assertEqual(1, len(cat.obsolete)) assert cat.get('Foo', 'Menu|File') is None message = cat.get('Foo', 'Menu|Edit') self.assertEqual('Voh', message.string) self.assertEqual(True, message.fuzzy) self.assertEqual('Menu|Edit', message.context)
def _read_existing_translations_for_language( self, language: str) -> catalog.Catalog: file_path = Path(str(self.locale_dir.joinpath(language, 'zordon.po'))) if file_path.is_file(): with file_path.open(mode='rb') as file: return pofile.read_po(file, locale=language, domain='zordon') return catalog.Catalog()
def import_csv_file(self, path): """Imports a CSV file formatted with locales in the header row and translations in the body rows.""" default_locale = self.pod.podspec.localization.get( 'default_locale', 'en') locales_to_catalogs = {} with open(path) as fp: reader = csv.DictReader(fp) for row in reader: if default_locale not in row: text = 'Locale {} not found in {}'.format( default_locale, path) raise Error(text) msgid = row[default_locale] msgid = msgid.decode('utf-8') for locale, translation in row.iteritems(): if locale == default_locale: continue translation = translation.decode('utf-8') message = catalog.Message(msgid, translation) if locale not in locales_to_catalogs: locales_to_catalogs[locale] = catalog.Catalog() locales_to_catalogs[locale][msgid] = message for locale, catalog_obj in locales_to_catalogs.iteritems(): fp = cStringIO.StringIO() pofile.write_po(fp, catalog_obj) fp.seek(0) content = fp.read() self.import_content(locale, content) fp.close()
def _download_content(self, stat): spreadsheet_id = stat.ident values = self._download_sheet(spreadsheet_id, stat.lang) values.pop(0) babel_catalog = catalog.Catalog(stat.lang) for row in values: # Skip empty rows. if not row or self._is_empty_row(row): continue source = row[0] translation = row[1] if len(row) > 1 else None babel_catalog.add(source, translation, auto_comments=[], context=None, flags=[]) updated_stat = base.TranslatorStat(url=stat.url, lang=stat.lang, downloaded=datetime.datetime.now(), source_lang=stat.source_lang, ident=stat.ident) fp = StringIO.StringIO() pofile.write_po(fp, babel_catalog) fp.seek(0) content = fp.read() return updated_stat, content
def test_mime_headers_contain_same_information_as_attributes(self): cat = catalog.Catalog() cat[''] = catalog.Message( '', "Last-Translator: Foo Bar <*****@*****.**>\n" + "Language-Team: de <*****@*****.**>\n" + "POT-Creation-Date: 2009-03-01 11:20+0200\n" + "PO-Revision-Date: 2009-03-09 15:47-0700\n") self.assertEqual(None, cat.locale) mime_headers = dict(cat.mime_headers) self.assertEqual('Foo Bar <*****@*****.**>', cat.last_translator) self.assertEqual('Foo Bar <*****@*****.**>', mime_headers['Last-Translator']) self.assertEqual('de <*****@*****.**>', cat.language_team) self.assertEqual('de <*****@*****.**>', mime_headers['Language-Team']) dt = datetime.datetime(2009, 3, 9, 15, 47, tzinfo=FixedOffsetTimezone(-7 * 60)) self.assertEqual(dt, cat.revision_date) formatted_dt = format_datetime(dt, 'yyyy-MM-dd HH:mmZ', locale='en') self.assertEqual(formatted_dt, mime_headers['PO-Revision-Date'])
def get_message_catalog(): cat = catalog.Catalog(fuzzy = False, charset = 'utf-8') # we need to retrieve all translatable strings within the source print("Parsing source for translatable strings...") tokens = extract.extract_from_dir( dirname = os.path.join(get_script_directory(), 'stereopoly'), ) for token in tokens: cat.add( token[2], #locations = (token[0], token[1], ), # currently bricks with 2.6.0 user_comments = token[3], context = token[4] ) print("Getting translatable strings from database...") session = db.setup()() boards = session.query(db.Board).all() for b in boards: for t in b.get_translatables(): cat.add( t['id'], user_comments = t['user_comments'] ) session.close() return cat
def main(): # Check arguments parser = argparse.ArgumentParser() parser.add_argument('pot_filename', type=argparse.FileType('r')) parser.add_argument('po_filename', type=argparse.FileType('w')) parser.add_argument('locale') args = parser.parse_args() # read POT file pot_cat = pofile.read_po(args.pot_filename, ignore_obsolete=True) # Create the new Catalog new_cat = catalog.Catalog(locale=args.locale, last_translator="pseudo.py", charset="utf-8") num_plurals = new_cat.num_plurals # Process messages from template for msg in pot_cat: if msg.pluralizable: msg.string = [ translate(u"{}:{}".format(i, msg.id[0])) for i in range(num_plurals) ] else: msg.string = translate(msg.id) new_cat[msg.id] = msg # Write "translated" PO file pofile.write_po(args.po_filename, new_cat, ignore_obsolete=True)
def _build_strings_catalog_from_sources(self) -> catalog.Catalog: strings_dict = self._get_translatable_strings() result = catalog.Catalog() for msg, locations in strings_dict.items(): result.add( msg, locations=locations, ) return result
def test_update_fuzzy_matching_no_cascading(self): cat = catalog.Catalog() cat.add('fo', 'Voh') cat.add('foo', 'Vohe') tmpl = catalog.Catalog() tmpl.add('fo') tmpl.add('foo') tmpl.add('fooo') cat.update(tmpl) assert 'fo' in cat assert 'foo' in cat self.assertEqual('Voh', cat['fo'].string) self.assertEqual(False, cat['fo'].fuzzy) self.assertEqual('Vohe', cat['foo'].string) self.assertEqual(False, cat['foo'].fuzzy) self.assertEqual('Vohe', cat['fooo'].string) self.assertEqual(True, cat['fooo'].fuzzy)
def test_stores_datetime_correctly(self): localized = catalog.Catalog() localized.locale = 'de_DE' localized[''] = catalog.Message( '', "POT-Creation-Date: 2009-03-09 15:47-0700\n" + "PO-Revision-Date: 2009-03-09 15:47-0700\n") for key, value in localized.mime_headers: if key in ('POT-Creation-Date', 'PO-Revision-Date'): self.assertEqual(value, '2009-03-09 15:47-0700')
def test_fuzzy_matching_regarding_plurals(self): cat = catalog.Catalog() cat.add(('foo', 'foh'), ('foo', 'foh')) ru = copy.copy(cat) ru.locale = 'ru_RU' ru.update(cat) self.assertEqual(True, ru['foo'].fuzzy) ru = copy.copy(cat) ru.locale = 'ru_RU' ru['foo'].string = ('foh', 'fohh', 'fohhh') ru.update(cat) self.assertEqual(False, ru['foo'].fuzzy)
def test_update_po_updates_pot_creation_date(self): template = catalog.Catalog() localized_catalog = copy.deepcopy(template) localized_catalog.locale = 'de_DE' self.assertNotEqual(template.mime_headers, localized_catalog.mime_headers) self.assertEqual(template.creation_date, localized_catalog.creation_date) template.creation_date = datetime.datetime.now() - \ datetime.timedelta(minutes=5) localized_catalog.update(template) self.assertEqual(template.creation_date, localized_catalog.creation_date)
def test_update_message_updates_comments(self): cat = catalog.Catalog() cat[u'foo'] = catalog.Message('foo', locations=[('main.py', 5)]) self.assertEqual(cat[u'foo'].auto_comments, []) self.assertEqual(cat[u'foo'].user_comments, []) # Update cat[u'foo'] with a new location and a comment cat[u'foo'] = catalog.Message('foo', locations=[('main.py', 7)], user_comments=['Foo Bar comment 1']) self.assertEqual(cat[u'foo'].user_comments, ['Foo Bar comment 1']) # now add yet another location with another comment cat[u'foo'] = catalog.Message('foo', locations=[('main.py', 9)], auto_comments=['Foo Bar comment 2']) self.assertEqual(cat[u'foo'].auto_comments, ['Foo Bar comment 2'])
def handle(self, *args, **options): for module in options['module']: for domain in options['domain']: potfile = POTFILE.format(module=module, domain=domain) for language in options['language']: # Get the locale code for the language code given and # work around broken django conversion function locales = {'ko': 'ko_KR', 'pl': 'pl_PL', 'tr': 'tr_TR'} locale = locales.get(language, translation.to_locale(language)) pofile = POFILE.format(module=module, locale=locale, domain=domain) # If this isn't a pseudo translation, execute pybabel if not options['pseudo']: if not os.path.exists(pofile): with open(pofile, 'wb') as fobj: fobj.write(b'') cmd = ('pybabel update -l {locale} -i {potfile} ' '-o {pofile}').format(locale=locale, potfile=potfile, pofile=pofile) call(cmd, shell=True) continue # Pseudo translation logic with open(potfile, 'r') as f: pot_cat = pofile.read_po(f, ignore_obsolete=True) new_cat = catalog.Catalog(locale=locale, last_translator="pseudo.py", charset="utf-8") num_plurals = new_cat.num_plurals for msg in pot_cat: if msg.pluralizable: msg.string = [ translate(u"{}:{}".format(i, msg.id[0])) for i in range(num_plurals) ] else: msg.string = translate(msg.id) new_cat[msg.id] = msg with open(pofile, 'w') as f: pofile.write_po(f, new_cat, ignore_obsolete=True)
def test_catalog_mime_headers(): created = datetime.datetime(1990, 4, 1, 15, 30, tzinfo=UTC) cat = catalog.Catalog(project='Foobar', version='1.0', creation_date=created) assert cat.mime_headers == [ ('Project-Id-Version', 'Foobar 1.0'), ('Report-Msgid-Bugs-To', 'EMAIL@ADDRESS'), ('POT-Creation-Date', '1990-04-01 15:30+0000'), ('PO-Revision-Date', 'YEAR-MO-DA HO:MI+ZONE'), ('Last-Translator', 'FULL NAME <EMAIL@ADDRESS>'), ('Language-Team', 'LANGUAGE <*****@*****.**>'), ('MIME-Version', '1.0'), ('Content-Type', 'text/plain; charset=utf-8'), ('Content-Transfer-Encoding', '8bit'), ('Generated-By', 'Babel %s\n' % catalog.VERSION), ]
def test_catalog_mime_headers_set_locale(): created = datetime.datetime(1990, 4, 1, 15, 30, tzinfo=UTC) revised = datetime.datetime(1990, 8, 3, 12, 0, tzinfo=UTC) cat = catalog.Catalog(locale='de_DE', project='Foobar', version='1.0', creation_date=created, revision_date=revised, last_translator='John Doe <*****@*****.**>', language_team='de_DE <*****@*****.**>') assert cat.mime_headers == [ ('Project-Id-Version', 'Foobar 1.0'), ('Report-Msgid-Bugs-To', 'EMAIL@ADDRESS'), ('POT-Creation-Date', '1990-04-01 15:30+0000'), ('PO-Revision-Date', '1990-08-03 12:00+0000'), ('Last-Translator', 'John Doe <*****@*****.**>'), ('Language-Team', 'de_DE <*****@*****.**>'), ('Plural-Forms', 'nplurals=2; plural=(n != 1)'), ('MIME-Version', '1.0'), ('Content-Type', 'text/plain; charset=utf-8'), ('Content-Transfer-Encoding', '8bit'), ('Generated-By', 'Babel %s\n' % catalog.VERSION), ]
def test_duplicate_location(self): cat = catalog.Catalog() cat.add('foo', locations=[('foo.py', 1)]) cat.add('foo', locations=[('foo.py', 1)]) self.assertEqual([('foo.py', 1)], cat['foo'].locations)
def test_duplicate_user_comment(self): cat = catalog.Catalog() cat.add('foo', user_comments=['A comment']) cat.add('foo', user_comments=['A comment', 'Another comment']) self.assertEqual(['A comment', 'Another comment'], cat['foo'].user_comments)