def test_unknown_escapes(): """Test that unknown escapes are processed correctly, with a warning, for string-array items as well. """ wfunc = TestWarnFunc() xml2po(read_xml(StringIO(''' <resources><string-array name="test"> <item>foo: \k</item> </string-array></resources>'''), warnfunc=wfunc)) assert len(wfunc.logs) == 1 assert 'unsupported escape' in wfunc.logs[0]
def test_unknown_escapes(): """Test that unknown escapes are processed correctly, with a warning, for string-array items as well. """ wfunc = TestWarnFunc() xml2po(StringIO(''' <resources><string-array name="test"> <item>foo: \k</item> </string-array></resources>'''), warnfunc=wfunc) assert len(wfunc.logs) == 1 assert 'unsupported escape' in wfunc.logs[0]
def test_translatable(): """Strings marked as translatable=False will be skipped. """ catalog = xml2po(StringIO( '<resources><string name="foo" translatable="false">bar</string></resources>')) assert len(catalog) == 0 catalog = xml2po(StringIO( '<resources><string name="foo" translatable="true">bar</string></resources>')) assert list(catalog)[1].id == 'bar' catalog = xml2po(StringIO( '<resources><string-array name="foo" translatable="false"><item>bla</item></string-array></resources>')) assert len(catalog) == 0
def test_formatted(): """Strings with "%1$s" and other Java-style format markers will be marked as c-format in the gettext flags. """ catalog = xml2po( StringIO( '<resources><string name="foo">foo %1$s bar</string></resources>')) assert "c-format" in list(catalog)[1].flags catalog = xml2po( StringIO( '<resources><string name="foo">foo %% bar</string></resources>')) assert "c-format" not in list(catalog)[1].flags catalog = xml2po( StringIO('<resources><string name="foo">foo</string></resources>')) assert "c-format" not in list(catalog)[1].flags catalog = xml2po( StringIO( '<resources><string-array name="foo"><item>foo %1$s bar</item></string-array></resources>' )) assert "c-format" in list(catalog)[1].flags catalog = xml2po( StringIO( '<resources><string-array name="foo"><item>foo %% bar</item></string-array></resources>' )) assert "c-format" not in list(catalog)[1].flags catalog = xml2po( StringIO( '<resources><string-array name="foo"><item>bar</item></string-array></resources>' )) assert "c-format" not in list(catalog)[1].flags # Babel likes to add python-format catalog = xml2po( StringIO( '<resources><string name="foo">foo %s bar</string></resources>')) assert "c-format" in list(catalog)[1].flags assert not "python-format" in list(catalog)[1].flags catalog = xml2po( StringIO( '<resources><string-array name="foo"><item>foo %s bar</item></string-array></resources>' )) assert "c-format" in list(catalog)[1].flags assert not "python-format" in list(catalog)[1].flags # Ensure that Babel doesn't add python-format on update ("export") # either. Yes, this is hard to get rid of. p = TempProject(default_xml={'foo': 'with %s format'}) try: p.program('init', {'de': ''}) p.program('export') catalog = p.get_po('de.po') assert not 'python-format' in list(catalog)[1].flags finally: p.delete()
def test_read_language(): """Test that when reading a translated xml file, the translations of a string array are properly matched up with to strings in the untranslated template. """ catalog, _ = xml2po( StringIO( """ <resources> <string-array name="colors"> <item>red</item> <item>green</item> </string-array> </resources> """ ), StringIO( """ <resources> <string-array name="colors"> <item>rot</item> <item>gruen</item> </string-array> </resources> """ ), ) assert len(list(catalog)) == 3 assert [m.context for m in catalog if m.id] == ["colors:0", "colors:1"] assert [m.id for m in catalog if m.id] == ["red", "green"] assert [m.string for m in catalog if m.id] == ["rot", "gruen"]
def test_read_language(): """Test that when reading a translated xml file, the translations of a string array are properly matched up with to strings in the untranslated template. """ catalog, _ = xml2po( read_xml( StringIO(''' <resources> <string-array name="colors"> <item>red</item> <item>green</item> </string-array> </resources> ''')), read_xml(StringIO(''' <resources> <string-array name="colors"> <item>rot</item> <item>gruen</item> </string-array> </resources> '''), language=Language('de'))) assert len(list(catalog)) == 3 assert [m.context for m in catalog if m.id] == ['colors:0', 'colors:1'] assert [m.id for m in catalog if m.id] == ['red', 'green'] assert [m.string for m in catalog if m.id] == ['rot', 'gruen']
def assert_convert(cls, xml, po=None, namespaces={}, warnfunc=None): """Helper that passes the string in ``xml`` through our xml parsing mechanism, and checks the resulting po catalog string against ``po``. If ``po`` is not given, we check against ``xml`` instead, i.e. expect the string to remain unchanged. """ key = 'test' extra = {} warnfunc = warnfunc or TestWarnFunc() catalog = xml2po(StringIO( '<resources %s><string name="%s">%s</string></resources>' % (" ".join([ 'xmlns:%s="%s"' % (name, url) for name, url in namespaces.items() ]), key, xml)), warnfunc=warnfunc) match = po if po is not None else xml for message in catalog: if message.context == key: #print "'%s' == '%s'" % (message.id, match) print repr(match), '==', repr(message.id) assert message.id == match break else: raise KeyError(warnfunc.logs)
def test_read_language(): """Test that when reading a translated xml file, the translations of a string array are properly matched up with to strings in the untranslated template. """ catalog, _ = xml2po(read_xml(StringIO(''' <resources> <string-array name="colors"> <item>red</item> <item>green</item> </string-array> </resources> ''')), read_xml(StringIO(''' <resources> <string-array name="colors"> <item>rot</item> <item>gruen</item> </string-array> </resources> '''), language=Language('de'))) assert len(list(catalog)) == 3 assert [m.context for m in catalog if m.id] == ['colors:0', 'colors:1'] assert [m.id for m in catalog if m.id] == ['red', 'green'] assert [m.string for m in catalog if m.id] == ['rot', 'gruen']
def assert_convert(cls, xml, po=None, namespaces={}, warnfunc=None): """Helper that passes the string in ``xml`` through our xml parsing mechanism, and checks the resulting po catalog string against ``po``. If ``po`` is not given, we check against ``xml`` instead, i.e. expect the string to remain unchanged. """ key = 'test' extra = {} warnfunc = warnfunc or TestWarnFunc() xmltree = read_xml(StringIO( '<resources %s><string name="%s">%s</string></resources>' % ( " ".join(['xmlns:%s="%s"' % (name, url) for name, url in namespaces.items()]), key, xml)), warnfunc=warnfunc) catalog = xml2po(xmltree, warnfunc=warnfunc) match = po if po is not None else xml for message in catalog: if message.context == key: #print "'%s' == '%s'" % (message.id, match) print repr(match), '==', repr(message.id) assert message.id == match break else: raise KeyError(warnfunc.logs)
def test_trailing_whitespace(): # [bug] Make sure that whitespace after the <string> tag does not # end up as part of the value. catalog = xml2po( StringIO( '<resources><string name="foo">bar</string> \t\t </resources>') ) assert list(catalog)[1].id == 'bar'
def test_string(self): catalog = xml2po(StringIO( '''<resources> <!-- Comment 1 --> <!-- Comment 2 --> <string name="string1">value1</string> <string name="string2">value2</string> </resources>''')) # TODO: Should those be stripped? Otherwise formatted (linebreaks etc)? assert catalog.get('value1', context='string1').auto_comments == [' Comment 1 ', ' Comment 2 '] assert catalog.get('value2', context='string2').auto_comments == []
def test_translatable(): """Strings marked as translatable=False will be skipped. """ catalog = xml2po( StringIO( '<resources><string name="foo" translatable="false">bar</string></resources>' )) assert len(catalog) == 0 catalog = xml2po( StringIO( '<resources><string name="foo" translatable="true">bar</string></resources>' )) assert list(catalog)[1].id == 'bar' catalog = xml2po( StringIO( '<resources><string-array name="foo" translatable="false"><item>bla</item></string-array></resources>' )) assert len(catalog) == 0
def test_translatable(self): """[bug] Make sure translatable=false and comments play nice together. """ catalog = xml2po( StringIO('''<resources> <!-- Comment 1 --> <!-- Comment 2 --> <string name="string1" translatable="false">value1</string> <string name="string2">value2</string> </resources>''')) # The comments of string1 do not end up with string2. assert catalog.get('value2', context='string2').auto_comments == []
def test_translatable(self): """[bug] Make sure translatable=false and comments play nice together. """ catalog = xml2po(StringIO( '''<resources> <!-- Comment 1 --> <!-- Comment 2 --> <string name="string1" translatable="false">value1</string> <string name="string2">value2</string> </resources>''')) # The comments of string1 do not end up with string2. assert catalog.get('value2', context='string2').auto_comments == []
def test_nameless(self): """This is an edge-case, but we don't (can't) process strings without a name. Comments are not passed along there either. """ catalog = xml2po(StringIO( '''<resources> <!-- Comment 1 --> <!-- Comment 2 --> <string>value1</string> <string name="string2">value2</string> </resources>''')) # The comments of string1 do not end up with string2. assert catalog.get('value2', context='string2').auto_comments == []
def test_read_template(): """Test basic read. """ catalog = xml2po(StringIO(''' <resources> <string-array name="colors"> <item>red</item> <item>green</item> </string-array> </resources> ''')) assert len(list(catalog)) == 3 assert [m.context for m in catalog if m.id] == ['colors:0', 'colors:1']
def test_formatted(): """Strings with "%1$s" and other Java-style format markers will be marked as c-format in the gettext flags. """ catalog = xml2po(StringIO( '<resources><string name="foo">foo %1$s bar</string></resources>')) assert "c-format" in list(catalog)[1].flags catalog = xml2po(StringIO( '<resources><string name="foo">foo %% bar</string></resources>')) assert "c-format" not in list(catalog)[1].flags catalog = xml2po(StringIO( '<resources><string name="foo">foo</string></resources>')) assert "c-format" not in list(catalog)[1].flags catalog = xml2po(StringIO( '<resources><string-array name="foo"><item>foo %1$s bar</item></string-array></resources>')) assert "c-format" in list(catalog)[1].flags catalog = xml2po(StringIO( '<resources><string-array name="foo"><item>foo %% bar</item></string-array></resources>')) assert "c-format" not in list(catalog)[1].flags catalog = xml2po(StringIO( '<resources><string-array name="foo"><item>bar</item></string-array></resources>')) assert "c-format" not in list(catalog)[1].flags # Babel likes to add python-format catalog = xml2po(StringIO( '<resources><string name="foo">foo %s bar</string></resources>')) assert "c-format" in list(catalog)[1].flags assert not "python-format" in list(catalog)[1].flags catalog = xml2po(StringIO( '<resources><string-array name="foo"><item>foo %s bar</item></string-array></resources>')) assert "c-format" in list(catalog)[1].flags assert not "python-format" in list(catalog)[1].flags # Ensure that Babel doesn't add python-format on update ("export") # either. Yes, this is hard to get rid of. p = TempProject(default_xml={'foo': 'with %s format'}) try: p.program('init', {'de': ''}) p.program('export') catalog = p.get_po('de.po') assert not 'python-format' in list(catalog)[1].flags finally: p.delete()
def test_nameless(self): """This is an edge-case, but we don't (can't) process strings without a name. Comments are not passed along there either. """ catalog = xml2po( StringIO('''<resources> <!-- Comment 1 --> <!-- Comment 2 --> <string>value1</string> <string name="string2">value2</string> </resources>''')) # The comments of string1 do not end up with string2. assert catalog.get('value2', context='string2').auto_comments == []
def test_string(self): catalog = xml2po( StringIO('''<resources> <!-- Comment 1 --> <!-- Comment 2 --> <string name="string1">value1</string> <string name="string2">value2</string> </resources>''')) # TODO: Should those be stripped? Otherwise formatted (linebreaks etc)? assert catalog.get('value1', context='string1').auto_comments == [ ' Comment 1 ', ' Comment 2 ' ] assert catalog.get('value2', context='string2').auto_comments == []
def test_xml_to_po_conversion_ru_pl(): mapping = { 'ru': { 0: 'loc many', # 0 яблок 1: 'loc one', # 1 яблоко 2: 'loc few', # 2 яблока 5: 'loc many', # 5 яблок 21: 'loc one', # 21 яблоко }, 'pl': { 0: 'loc many', # 0 jabłek 1: 'loc one', # 1 jabłko 2: 'loc few', # 2 jabłka 22: 'loc few', # 22 jabłka 25: 'loc many', # 25 jabłek } } for lang in ['ru', 'pl']: catalog, _ = xml2po(read_xml( StringIO(''' <resources> <plurals name="plurals_test"> <item quantity="one">one</item> <item quantity="other">other</item> </plurals> </resources> ''')), read_xml(StringIO(''' <resources> <plurals name="plurals_test"> <item quantity="one">loc one</item> <item quantity="few">loc few</item> <item quantity="many">loc many</item> <item quantity="other">loc other</item> </plurals> </resources> '''), language=Language(lang)), warnfunc=TestWarnFunc()) # message msg = list(catalog)[1] assert_equal(msg.string, ('loc one', 'loc few', 'loc many', 'loc other')) # translation works properly trans = catalog_to_translations(catalog) for num, form in mapping[lang].items(): assert_equal(trans.unpgettext('plurals_test', 'one', 'other', num), form)
def assert_convert_error(cls, xml, error_match): """Ensure that the given xml resource string cannot be processed and results in the given error. """ wfunc = TestWarnFunc() key = 'test' catalog = xml2po(read_xml( StringIO('<resources><string name="%s">%s</string></resources>' % ( key, xml)), warnfunc=wfunc)) assert not catalog.get(xml, context=key) for line in wfunc.logs: if error_match in line: return assert False, "error output not matched"
def assert_convert_error(cls, xml, error_match): """Ensure that the given xml resource string cannot be processed and results in the given error. """ wfunc = TestWarnFunc() key = 'test' catalog = xml2po( StringIO('<resources><string name="%s">%s</string></resources>' % (key, xml)), warnfunc=wfunc) assert not catalog.get(xml, context=key) for line in wfunc.logs: if error_match in line: return assert False, "error output not matched"
def test_string_array(self): catalog = xml2po(StringIO( '''<resources> <!-- Comment 1 --> <!-- Comment 2 --> <string-array name="array"> <item>item1</item> <!-- this will be ignored --> <item>item2</item> </string-array> <string name="string">value</string> </resources>''')) assert catalog.get('item1', context='array:0').auto_comments == [' Comment 1 ', ' Comment 2 '] assert catalog.get('item2', context='array:1').auto_comments == [' Comment 1 ', ' Comment 2 '] assert catalog.get('value', context='string').auto_comments == []
def test_read_language_xml(): """Convert a XML resource to a catalog, while matching strings up with translations from another resource. (what the init command does). """ wfunc = TestWarnFunc() catalog, _ = xml2po( read_xml( StringIO(''' <resources> <plurals name="foo"> <item quantity="one">one</item> <item quantity="other">other</item> </plurals> </resources> ''')), read_xml(StringIO(''' <resources> <plurals name="foo"> <item quantity="one">ro one</item> <item quantity="few">ro few</item> <item quantity="many">ro many</item> <item quantity="other">ro other</item> </plurals> </resources> '''), language=Language('ro')), # Romanian warnfunc=wfunc) # A warning has been written for the unsupported quantity assert_equal(len(wfunc.logs), 1) assert 'uses quantity "many", which is not supported ' in wfunc.logs[0] assert_equal([m.id for m in catalog if m.id], [('one', 'other')]) # Note: Romanian does not use the "many" string, so it is not included. assert_equal([m.string for m in catalog if m.id], [('ro one', 'ro few', 'ro other')]) # Make sure the catalog has the proper header assert_equal(catalog.num_plurals, 3) print(catalog.plural_expr) assert_equal( catalog.plural_expr, '((((!((0 == 0))) || ((n == 0))) || (((n % 100) >= 2 && (n % 100) <= 19))) ? 1 : (((n == 1)) && ((0 == 0))) ? 0 : 2)' )
def test_xml_to_po_conversion_ru_pl(): mapping = { 'ru': { 0: 'loc many', # 0 яблок 1: 'loc one', # 1 яблоко 2: 'loc few', # 2 яблока 5: 'loc many', # 5 яблок 21: 'loc one', # 21 яблоко }, 'pl': { 0: 'loc many', # 0 jabłek 1: 'loc one', # 1 jabłko 2: 'loc few', # 2 jabłka 22: 'loc few', # 22 jabłka 25: 'loc many', # 25 jabłek } } for lang in ['ru', 'pl']: catalog, _ = xml2po(read_xml(StringIO(''' <resources> <plurals name="plurals_test"> <item quantity="one">one</item> <item quantity="other">other</item> </plurals> </resources> ''')), read_xml(StringIO(''' <resources> <plurals name="plurals_test"> <item quantity="one">loc one</item> <item quantity="few">loc few</item> <item quantity="many">loc many</item> <item quantity="other">loc other</item> </plurals> </resources> '''), language=Language(lang)), warnfunc=TestWarnFunc()) # message msg = list(catalog)[1] assert msg.string == ('loc one', 'loc few', 'loc many', 'loc other') # translation works properly trans = catalog_to_translations(catalog) for num, form in mapping[lang].items(): assert trans.unpgettext('plurals_test', 'one', 'other', num) == form
def test_read_order(): """Test that a strings of a string-array have the same position in the final catalog as the string-array had in the xml file, e.g. order is maintained for the string-array. """ catalog = xml2po(StringIO(''' <resources> <string name="before">foo</string> <string-array name="colors"> <item>red</item> <item>green</item> </string-array> <string name="after">bar</string> </resources> ''')) assert len(list(catalog)) == 5 assert [m.context for m in catalog if m.id] == [ 'before', 'colors:0', 'colors:1', 'after']
def test_string_array(self): catalog = xml2po( StringIO('''<resources> <!-- Comment 1 --> <!-- Comment 2 --> <string-array name="array"> <item>item1</item> <!-- this will be ignored --> <item>item2</item> </string-array> <string name="string">value</string> </resources>''')) assert catalog.get('item1', context='array:0').auto_comments == [ ' Comment 1 ', ' Comment 2 ' ] assert catalog.get('item2', context='array:1').auto_comments == [ ' Comment 1 ', ' Comment 2 ' ] assert catalog.get('value', context='string').auto_comments == []
def test_read_language_xml(): """Convert a XML resource to a catalog, while matching strings up with translations from another resource. (what the init command does). """ wfunc = TestWarnFunc() catalog, _ = xml2po(read_xml(StringIO(''' <resources> <plurals name="foo"> <item quantity="one">one</item> <item quantity="other">other</item> </plurals> </resources> ''')), read_xml(StringIO(''' <resources> <plurals name="foo"> <item quantity="one">ro one</item> <item quantity="few">ro few</item> <item quantity="many">ro many</item> <item quantity="other">ro other</item> </plurals> </resources> '''), language=Language('ro')), # Romanian warnfunc=wfunc) # A warning has been written for the unsupported quantity assert len(wfunc.logs) == 1 assert 'uses quantity "many", which is not supported ' in wfunc.logs[0] assert [m.id for m in catalog if m.id] == [('one', 'other')] # Note: Romanian does not use the "many" string, so it is not included. assert [m.string for m in catalog if m.id] == [ ('ro few', 'ro one', 'ro other')] # Make sure the catalog has the proper header assert catalog.num_plurals == 3 print(catalog.plural_expr) assert catalog.plural_expr == '(((n == 0) || ((n != 1) && (((n % 100) >= 1 && (n % 100) <= 19)))) ? 1 : (n == 1) ? 0 : 2)'
def test_trailing_whitespace(): # [bug] Make sure that whitespace after the <string> tag does not # end up as part of the value. catalog = xml2po(StringIO( '<resources><string name="foo">bar</string> \t\t </resources>')) assert list(catalog)[1].id == 'bar'
def xmlstr2po(string): return xml2po(read_xml(StringIO(string)))
def make_raw(cls, content): logger = TestWarnFunc() return xml2po(read_xml(StringIO(content), warnfunc=logger), warnfunc=logger), logger.logs