i18nspector-0.13.4/0000755000000000000000000000000012312562473013761 5ustar00rootroot00000000000000i18nspector-0.13.4/tests/0000755000000000000000000000000012312562472015122 5ustar00rootroot00000000000000i18nspector-0.13.4/tests/test_version.py0000644000000000000000000000356212312562472020226 0ustar00rootroot00000000000000# Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import os from nose.tools import ( assert_equal, ) from lib.cli import __version__ here = os.path.dirname(__file__) docdir = os.path.join(here, os.pardir, 'doc') def test_changelog(): path = os.path.join(docdir, 'changelog') with open(path, 'rt', encoding='UTF-8') as file: line = file.readline() changelog_version = line.split()[1].strip('()') assert_equal(changelog_version, __version__) def test_manpage(): path = os.path.join(docdir, 'i18nspector.txt') manpage_version = None with open(path, 'rt', encoding='UTF-8') as file: for line in file: if line.startswith(':version:'): manpage_version = line.split()[-1] break assert_equal(manpage_version, __version__) # vim:ts=4 sw=4 et i18nspector-0.13.4/tests/test_terminal.py0000644000000000000000000000514712312562472020355 0ustar00rootroot00000000000000# Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import pty import os import sys from nose.tools import ( assert_equal, ) from . import aux import lib.terminal as T def test_strip_delay(): def t(s, r=b''): assert_equal(T._strip_delay(s), r) t(b'$<1>') t(b'$<2/>') t(b'$<3*>') t(b'$<4*/>') t(b'$<.5*/>') t(b'$<0.6*>') s = b'$<\x9b20>' t(s, s) def _get_colors(): return ( value for name, value in sorted(vars(T.colors).items()) if name.isalpha() ) def test_dummy(): for i in _get_colors(): assert_equal(T.attr_fg(i), '') assert_equal(T.attr_reset(), '') def _setup_tty(term): master_fd, slave_fd = pty.openpty() os.dup2(slave_fd, pty.STDOUT_FILENO) sys.stdout = sys.__stdout__ os.environ['TERM'] = term T.initialize() @aux.fork_isolation def test_vt100(): _setup_tty('vt100') for i in _get_colors(): assert_equal(T.attr_fg(i), '') assert_equal(T.attr_reset(), '\x1b[m\x0f') @aux.fork_isolation def test_ansi(): _setup_tty('ansi') assert_equal(T.attr_fg(T.colors.black), '\x1b[30m') assert_equal(T.attr_fg(T.colors.red), '\x1b[31m') assert_equal(T.attr_fg(T.colors.green), '\x1b[32m') assert_equal(T.attr_fg(T.colors.yellow), '\x1b[33m') assert_equal(T.attr_fg(T.colors.blue), '\x1b[34m') assert_equal(T.attr_fg(T.colors.magenta), '\x1b[35m') assert_equal(T.attr_fg(T.colors.cyan), '\x1b[36m') assert_equal(T.attr_fg(T.colors.white), '\x1b[37m') assert_equal(T.attr_reset(), '\x1b[0;10m') # vim:ts=4 sw=4 et i18nspector-0.13.4/tests/test_tags.py0000644000000000000000000000325412312562472017475 0ustar00rootroot00000000000000# Copyright © 2012, 2013, 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import lib.tags as M from nose.tools import ( assert_equal, ) class test_escape: esc = staticmethod(M._escape) # FIXME: _escape is private def t(self, s, expected): assert_equal( self.esc(s), expected ) def test_safe(self): s = 'fox' self.t(s, s) def test_trailing_newline(self): s = 'fox\n' self.t(s, repr(s)) def test_colon(self): s = 'fox:' self.t(s, repr(s)) def test_space(self): s = 'brown fox' self.t(s, repr(s)) # vim:ts=4 sw=4 et i18nspector-0.13.4/tests/test_polib4us.py0000644000000000000000000000341312312562472020275 0ustar00rootroot00000000000000# Copyright © 2013, 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import polib from nose.tools import ( assert_true, ) from . import aux import lib.polib4us as M minimal_header = r''' msgid "" msgstr "Content-Type: text/plain; charset=US-ASCII\n" ''' class test_codecs: @aux.fork_isolation def test_trailing_obsolete_message(self): s = minimal_header + ''' msgid "a" msgstr "b" #~ msgid "b" #~ msgstr "c" ''' def t(): with aux.temporary_file(mode='wt', encoding='ASCII') as file: file.write(s) file.flush() po = polib.pofile(file.name) assert_true(po[-1].obsolete) t() M.install_patches() t() # vim:ts=4 sw=4 et i18nspector-0.13.4/tests/test_misc.py0000644000000000000000000001213312312562472017466 0ustar00rootroot00000000000000# Copyright © 2012, 2013, 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import datetime import os import nose from nose.tools import ( assert_equal, assert_false, assert_is_instance, assert_is_not_none, assert_raises, assert_true, ) from . import aux import lib.misc as M def sorted_iterable(): yield 1 yield 2 yield 4 def unsorted_iterable(): yield 1 yield 4 yield 2 class test_is_sorted: def test_sorted(self): iterable = sorted_iterable() is_sorted = M.is_sorted(iterable) assert_true(is_sorted) def test_not_sorted(self): iterable = unsorted_iterable() is_sorted = M.is_sorted(iterable) assert_false(is_sorted) class test_check_sorted: def test_sorted(self): iterable = sorted_iterable() M.check_sorted(iterable) def test_not_sorted(self): iterable = unsorted_iterable() with assert_raises(M.DataIntegrityError): M.check_sorted(iterable) class test_os_release: def t(self, path, **like): os_release = M.OSRelease(path=path) for opsys, expected in like.items(): if expected: assert_true(os_release.is_like(opsys)) else: assert_false(os_release.is_like(opsys)) def _tmpfile(self, contents): file = aux.temporary_file( mode='wt', encoding='ASCII' ) file.write(contents) file.flush() return file def test_nonexistent(self): with aux.temporary_directory() as tmpdir: self.t(os.path.join(tmpdir, 'nonexistent'), debian=False, ubuntu=False, pld=False, ) def test_io_error(self): if os.getuid() == 0: raise nose.SkipTest('this test must not be run as root') with self._tmpfile('') as file: os.chmod(file.name, 0) with assert_raises(IOError): self.t(file.name) def test_syntax_error(self): with self._tmpfile('ID="debian\n') as file: self.t(file.name, debian=False, ubuntu=False, pld=False, ) def test_empty(self): with self._tmpfile('') as file: self.t(file.name, debian=False, ubuntu=False, pld=False, ) def test_debian(self): with self._tmpfile('ID="debian"\n') as file: self.t(file.name, debian=True, ubuntu=False, pld=False, ) def test_debian_derivative(self): with self._tmpfile('ID="ubuntu"\nID_LIKE="debian"') as file: self.t(file.name, debian=True, ubuntu=True, pld=False, ) def test_non_debian(self): with self._tmpfile('ID="pld"\n') as file: self.t(file.name, debian=False, ubuntu=False, pld=True, ) def test_none(self): with self._tmpfile('') as file: os_release = M.OSRelease(path=file.name) with assert_raises(TypeError): os_release.is_like(None) def test_utc_now(): now = M.utc_now() assert_is_instance(now, datetime.datetime) assert_is_not_none(now.tzinfo) assert_equal(now.tzinfo.utcoffset(now), datetime.timedelta(0)) class test_format_range: def t(self, x, y, max, expected): assert_equal( M.format_range(range(x, y), max=max), expected ) def test_max_is_lt_4(self): with assert_raises(ValueError): self.t(5, 10, 3, None) def test_len_lt_max(self): self.t(5, 10, 4, '5, 6, ..., 9') self.t(23, 43, 6, '23, 24, 25, 26, ..., 42') def test_len_eq_max(self): self.t(5, 10, 5, '5, 6, 7, 8, 9') def test_len_gt_max(self): self.t(5, 10, 6, '5, 6, 7, 8, 9') def test_huge(self): self.t(5, 42 ** 17, 5, '5, 6, 7, ..., 3937657486715347520027492351') # vim:ts=4 sw=4 et i18nspector-0.13.4/tests/test_ling.py0000644000000000000000000002706412312562472017475 0ustar00rootroot00000000000000# Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. from nose.tools import ( assert_equal, assert_false, assert_in, assert_is, assert_is_instance, assert_is_none, assert_not_equal, assert_not_in, assert_raises, assert_true, ) from . import aux import lib.ling import lib.encodings L = lib.ling T = lib.ling.Language E = lib.encodings class test_fix_codes: def t(self, l1, l2): lang = L.parse_language(l1) assert_equal(str(lang), l1) if l1 == l2: assert_is_none(lang.fix_codes()) else: assert_is(lang.fix_codes(), True) assert_equal(str(lang), l2) def test_2_to_2(self): self.t('grc', 'grc') self.t('grc_GR', 'grc_GR') def test_1_to_1(self): self.t('el', 'el') self.t('el_GR', 'el_GR') def test_2t_to_1(self): self.t('ell', 'el') self.t('ell_GR', 'el_GR') def test_2b_to_1(self): self.t('gre', 'el') self.t('gre_GR', 'el_GR') def test_ll_not_found(self): with assert_raises(L.FixingLanguageCodesFailed): self.t('ry', '') def test_cc_not_found(self): with assert_raises(L.FixingLanguageCodesFailed): self.t('el_RY', '') class test_language_equality: # ==, !=, is_almost_equal() def test_eq(self): l1 = T('el', 'GR') l2 = T('el', 'GR') assert_equal(l1, l2) assert_equal(l2, l1) def test_ne(self): l1 = T('el') l2 = T('el', 'GR') assert_not_equal(l1, l2) assert_not_equal(l2, l1) def test_ne_other_type(self): l1 = T('el') assert_not_equal(l1, 42) assert_not_equal(42, l1) def test_almost_equal(self): l1 = T('el') l2 = T('el', 'GR') assert_true(l1.is_almost_equal(l2)) assert_true(l2.is_almost_equal(l1)) def test_not_almost_equal(self): l1 = T('el', 'GR') l2 = T('grc', 'GR') assert_false(l1.is_almost_equal(l2)) assert_false(l2.is_almost_equal(l1)) def test_not_almost_equal_other_type(self): l1 = T('el') with assert_raises(TypeError): l1.is_almost_equal(42) class test_remove_encoding: def t(self, l1, l2): lang = L.parse_language(l1) assert_equal(str(lang), l1) if l1 == l2: assert_is_none(lang.remove_encoding()) else: assert_is(lang.remove_encoding(), True) assert_equal(str(lang), l2) def test_without_encoding(self): self.t('el', 'el') def test_with_encoding(self): self.t('el.UTF-8', 'el') class test_remove_nonlinguistic_modifier: def t(self, l1, l2): lang = L.parse_language(l1) assert_equal(str(lang), l1) if l1 == l2: assert_is_none(lang.remove_nonlinguistic_modifier()) else: assert_is(lang.remove_nonlinguistic_modifier(), True) assert_equal(str(lang), l2) def test_quot(self): self.t('en@quot', 'en@quot') self.t('en@boldquot', 'en@boldquot') def test_latin(self): self.t('sr@latin', 'sr@latin') def test_euro(self): self.t('de_AT@euro', 'de_AT') class test_lookup_territory_code: def test_found(self): cc = L.lookup_territory_code('GR') assert_equal(cc, 'GR') def test_not_found(self): cc = L.lookup_territory_code('RG') assert_is_none(cc) class test_get_language_for_name: def t(self, name, expected): lang = L.get_language_for_name(name) assert_is_instance(lang, T) assert_equal(str(lang), expected) def test_found(self): self.t('Greek', 'el') def test_found_multi(self): self.t('Old Church Slavonic', 'cu') def test_found_as_ascii(self): self.t('Norwegian Bokmål', 'nb') def test_found_semicolon(self): self.t('Chichewa; Nyanja', 'ny') def test_found_comma(self): self.t('Ndebele, South', 'nr') def test_found_comma_as_semicolon(self): self.t('Pashto, Pushto', 'ps') def test_not_found(self): with assert_raises(LookupError): self.t('Nadsat', None) class test_parse_language: def test_ll(self): lang = L.parse_language('el') assert_equal(lang.language_code, 'el') assert_is_none(lang.territory_code) assert_is_none(lang.encoding) assert_is_none(lang.modifier) def test_lll(self): lang = L.parse_language('ell') assert_equal(lang.language_code, 'ell') assert_is_none(lang.territory_code) assert_is_none(lang.encoding) assert_is_none(lang.modifier) def test_ll_cc(self): lang = L.parse_language('el_GR') assert_equal(lang.language_code, 'el') assert_equal(lang.territory_code, 'GR') assert_is_none(lang.encoding) assert_is_none(lang.modifier) def test_ll_cc_enc(self): lang = L.parse_language('el_GR.UTF-8') assert_equal(lang.language_code, 'el') assert_equal(lang.territory_code, 'GR') assert_equal(lang.encoding, 'UTF-8') assert_is_none(lang.modifier) def test_ll_cc_modifier(self): lang = L.parse_language('en_US@quot') assert_equal(lang.language_code, 'en') assert_equal(lang.territory_code, 'US') assert_is_none(lang.encoding) assert_equal(lang.modifier, 'quot') def test_syntax_error(self): with assert_raises(L.LanguageSyntaxError): L.parse_language('GR') class test_get_primary_languages: def test_found(self): langs = L.get_primary_languages() assert_in('el', langs) def test_not_found(self): langs = L.get_primary_languages() assert_not_in('ry', langs) def test_iso_639(self): def t(lang_str): lang = L.parse_language(lang_str) assert_is_none(lang.fix_codes()) assert_equal(str(lang), lang_str) for lang_str in L.get_primary_languages(): yield t, lang_str class test_get_plural_forms: def t(self, lang): lang = L.parse_language(lang) return lang.get_plural_forms() def test_found_ll(self): assert_equal( self.t('el'), ['nplurals=2; plural=n != 1;'] ) def test_found_ll_cc(self): assert_equal( self.t('el_GR'), ['nplurals=2; plural=n != 1;'] ) def test_en_ca(self): assert_equal( self.t('en'), self.t('en_CA'), ) def test_pt_br(self): assert_not_equal( self.t('pt'), self.t('pt_BR'), ) def test_not_known(self): assert_is_none(self.t('la')) def test_not_found(self): assert_is_none(self.t('ry')) class test_principal_territory: def test_found_2(self): # el -> el_GR lang = L.parse_language('el') cc = lang.get_principal_territory_code() assert_equal(cc, 'GR') def test_remove_2(self): # el_GR -> el lang = L.parse_language('el_GR') assert_equal(str(lang), 'el_GR') rc = lang.remove_principal_territory_code() assert_is(rc, True) assert_equal(str(lang), 'el') def test_found_3(self): # ang -> ang_GB lang = L.parse_language('ang') cc = lang.get_principal_territory_code() assert_equal(cc, 'GB') def test_remove_3(self): # ang_GB -> ang lang = L.parse_language('ang_GB') assert_equal(str(lang), 'ang_GB') rc = lang.remove_principal_territory_code() assert_is(rc, True) assert_equal(str(lang), 'ang') def test_no_principal_territory_code(self): # en -/-> en_US lang = L.parse_language('en') cc = lang.get_principal_territory_code() assert_is_none(cc) def test_no_remove_principal_territory_code(self): # en_US -/-> en lang = L.parse_language('en_US') assert_equal(str(lang), 'en_US') rc = lang.remove_principal_territory_code() assert_is_none(rc) assert_equal(str(lang), 'en_US') def test_not_found(self): lang = L.parse_language('ry') cc = lang.get_principal_territory_code() assert_equal(cc, None) class test_unrepresentable_characters: def test_ll_bad(self): lang = L.parse_language('pl') result = lang.get_unrepresentable_characters('ISO-8859-1') assert_not_equal(result, []) def test_ll_ok(self): lang = L.parse_language('pl') result = lang.get_unrepresentable_characters('ISO-8859-2') assert_equal(result, []) def test_ll_cc_bad(self): lang = L.parse_language('pl_PL') result = lang.get_unrepresentable_characters('ISO-8859-1') assert_not_equal(result, []) def test_ll_cc_ok(self): lang = L.parse_language('pl_PL') result = lang.get_unrepresentable_characters('ISO-8859-2') assert_equal(result, []) def test_ll_mod_bad(self): lang = L.parse_language('en@quot') result = lang.get_unrepresentable_characters('ISO-8859-1') assert_not_equal(result, []) def test_ll_mod_ok(self): lang = L.parse_language('en@quot') result = lang.get_unrepresentable_characters('UTF-8') assert_equal(result, []) def test_ll_cc_mod_bad(self): lang = L.parse_language('en_US@quot') result = lang.get_unrepresentable_characters('ISO-8859-1') assert_not_equal(result, []) def test_ll_cc_mod_ok(self): lang = L.parse_language('en_US@quot') result = lang.get_unrepresentable_characters('UTF-8') assert_equal(result, []) def test_ll_optional(self): # U+0178 (LATIN CAPITAL LETTER Y WITH DIAERESIS) is not representable # in ISO-8859-1, but we normally turn a blind eye to this. lang = L.parse_language('fr') result = lang.get_unrepresentable_characters('ISO-8859-1') assert_equal(result, []) result = lang.get_unrepresentable_characters('ISO-8859-1', strict=True) assert_not_equal(result, []) def test_ll_not_found(self): lang = L.parse_language('ry') result = lang.get_unrepresentable_characters('ISO-8859-1') assert_is_none(result) @aux.fork_isolation def test_extra_encoding(self): encoding = 'GEORGIAN-PS' lang = L.parse_language('pl') with assert_raises(LookupError): ''.encode(encoding) E.install_extra_encodings() result = lang.get_unrepresentable_characters(encoding) assert_not_equal(result, []) # vim:ts=4 sw=4 et i18nspector-0.13.4/tests/test_iconv.py0000644000000000000000000000337212312562472017656 0ustar00rootroot00000000000000# Copyright © 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. from nose.tools import ( assert_equal, ) import lib.iconv as M class _test: u = None b = None e = None def test_encode(self): b = M.encode(self.u, self.e) assert_equal(b, self.b) def test_decode(self): u = M.decode(self.b, self.e) assert_equal(u, self.u) class test_iso2(_test): u = 'Żrą łódź? Część miń!' b = b'\xAFr\xB1 \xB3\xF3d\xBC? Cz\xEA\xB6\xE6 mi\xF1!' e = 'ISO-8859-2' class test_tcvn(_test): u = 'Do bạch kim rất quý, sẽ để lắp vô xương' b = b'Do b\xB9ch kim r\xCAt qu\xFD, s\xCF \xAE\xD3 l\xBEp v\xAB x\xAD\xACng' e = 'TCVN-5712' # vim:ts=4 sw=4 et i18nspector-0.13.4/tests/test_gettext.py0000644000000000000000000004122212312562472020220 0ustar00rootroot00000000000000# Copyright © 2012, 2013, 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import datetime from nose.tools import ( assert_equal, assert_false, assert_is_instance, assert_is_none, assert_is_not_none, assert_less, assert_raises, assert_true, ) import lib.gettext as M class test_header_fields: def test_nonempty(self): # XXX Update this number after editing data/header-fields: expected = 12 assert_equal(len(M.header_fields), expected) def test_no_x(self): for field in M.header_fields: assert_false(field.startswith('X-')) def test_valid(self): for field in M.header_fields: assert_true(M.is_valid_field_name(field)) class test_header_parser: def t(self, message, expected): parsed = list(M.parse_header(message)) assert_equal(parsed, expected) def test_ok(self): self.t( 'Menu: spam\nVikings: yes\n', [{'Menu': 'spam'}, {'Vikings': 'yes'}], ) def test_invalid_field_name(self): self.t( 'Menu :spam\nVikings: yes\n', ['Menu :spam', {'Vikings': 'yes'}], ) def test_no_field(self): self.t( 'Spam\nVikings: yes\n', ['Spam', {'Vikings': 'yes'}], ) def test_continuation(self): self.t( 'Menu: spam,\n eggs\nVikings: yes\n', [{'Menu': 'spam,'}, ' eggs', {'Vikings': 'yes'}], ) class test_plural_exp: error = M.PluralFormsSyntaxError def t(self, s, n=None, fn=None): f = M.parse_plural_expression(s) if n is not None: assert_is_not_none(fn) assert_equal(f(n), fn) def test_const(self): n = 42 self.t(str(n), 0, n) def test_const_overflow(self): m = (1 << 32) - 1 self.t(str(m), m, m) with assert_raises(OverflowError): self.t(str(m + 1), m + 1, False) self.t(str(m + 1), m + 42, False) def test_var(self): n = 42 self.t('n', n, n) def test_var_overflow(self): m = (1 << 32) - 1 self.t('n', m, m) with assert_raises(OverflowError): self.t('n', m + 1, False) self.t('42', m + 1, 42) def test_add(self): self.t('17 + n', 6, 23) def test_add_overflow(self): m = (1 << 32) - 1 self.t('n + 42', m - 42, m) with assert_raises(OverflowError): self.t('n + 42', m - 41, False) self.t('n + 42', m - 23, False) def test_sub(self): self.t('n - 23', 37, 14) def test_sub_overflow(self): with assert_raises(OverflowError): self.t('n - 23', 6, False) def test_mul(self): self.t('6 * n', 7, 42) def test_mul_overflow(self): m = (1 << 32) - 1 assert m % 17 == 0 self.t('n * 17', m / 17, m) with assert_raises(OverflowError): self.t('n * 17', (m / 17) + 1, False) self.t('n * 2', (m + 1) / 2, False) def test_div(self): self.t('105 / n', 17, 6) def test_div_by_0(self): with assert_raises(ZeroDivisionError): self.t('105 / n', 0, False) def test_mod(self): self.t('105 % n', 17, 3) def test_mod_by_0(self): with assert_raises(ZeroDivisionError): self.t('105 % n', 0, False) def test_and(self): self.t('n && 6', 7, 1) self.t('n && 6', 0, 0) self.t('n && (6 / 0)', 0, 0) # no ZeroDivisionError self.t('n && 0', 7, 0) self.t('n && 0', 0, 0) def test_or(self): self.t('n || 6', 7, 1) self.t('n || (6 / 0)', 7, 1) # no ZeroDivisionError self.t('n || 6', 0, 1) self.t('n || 0', 7, 1) self.t('n || 0', 0, 0) def test_gt(self): self.t('n > 37', 23, 0) self.t('n > 37', 37, 0) self.t('n > 37', 42, 1) def test_ge(self): self.t('n >= 37', 23, 0) self.t('n >= 37', 37, 1) self.t('n >= 37', 42, 1) def test_lt(self): self.t('n < 37', 23, 1) self.t('n < 37', 37, 0) self.t('n < 37', 42, 0) def test_le(self): self.t('n <= 37', 23, 1) self.t('n <= 37', 37, 1) self.t('n <= 37', 42, 0) def test_eq(self): self.t('n == 37', 23, 0) self.t('n == 37', 37, 1) self.t('n == 37', 42, 0) def test_ne(self): self.t('n != 37', 23, 1) self.t('n != 37', 37, 0) self.t('n != 37', 42, 1) def test_multi_compare(self): self.t('1 < n == 3 <= 4', 1, 0) # False in Python self.t('1 < n == 3 <= 4', 2, 1) # False in Python self.t('1 < n == 3 <= 4', 3, 1) # True in Python self.t('1 < n == 3 <= 4', 4, 1) # False in Python self.t('2 == 2 == n', 2, 0) # True in Python self.t('2 == 2 == n', 1, 1) # False in Python def test_neg(self): self.t('! n', 0, 1) self.t('! n', 1, 0) self.t('! n', 69, 0) def test_neg_precedence(self): self.t('! 6 + 7', 0, 7) self.t('0 + ! 0') def test_conditional(self): s = 'n ? 3 : 7' self.t(s, 0, 7) self.t(s, 1, 3) def test_nested_conditional(self): self.t('(2 ? 3 : 7) ? 23 : 37') def test_unary_plus(self): with assert_raises(self.error): self.t('-37') with assert_raises(self.error): self.t('23 + (-37)') def test_unary_minus(self): with assert_raises(self.error): self.t('+42') with assert_raises(self.error): self.t('23 + (+37)') def test_unbalanced_parentheses(self): with assert_raises(self.error): self.t('(6 * 7') with assert_raises(self.error): self.t('6 * 7)') def test_dangling_binop(self): with assert_raises(self.error): self.t('6 +') def test_junk_token(self): with assert_raises(self.error): self.t('6 # 7') def test_exotic_whitespace(self): with assert_raises(self.error): self.t('6 *\xA07') class test_codomain: def t(self, s, min_, max_=None): if max_ is None: max_ = min_ f = M.parse_plural_expression(s) cd = f.codomain() if min_ is None: assert max_ is None assert_is_none(cd) else: assert_equal(cd, (min_, max_)) def test_num(self): self.t('0', 0, 0) self.t('42', 42, 42) m = (1 << 32) - 1 self.t(str(m), m, m) # no overflow self.t(str(m + 1), None) # overflow self.t(str(m + 23), None) # overflow def test_zero_div(self): self.t('n / 0', None) self.t('(n / 0) + 23', None) self.t('23 + (n / 0)', None) self.t('! (n / 0)', None) self.t('0 < n/0', None) self.t('n/0 < 0', None) self.t('0 < n/0 < 0', None) def test_mod(self): self.t('n % 42', 0, 41) def test_mod_mod(self): self.t('(23 + n%15) % 42', 23, 37) def test_mod_0(self): self.t('n % 0', None) def test_add(self): self.t( '(6 + n%37) + (7 + n%23)', (6 + 7), 6 + 7 + 36 + 22 ) def test_add_max_overflow(self): m = (1 << 32) - 1 self.t( '(37 + n%4242424242) + (23 + n%4242424242)', 37 + 23, m ) def test_add_min_overflow(self): self.t( '(4242424242 + n%37) + (4242424242 + n%23)', None ) def test_sub(self): self.t( '(6 + n%37) - (7 + n%23)', 0, 6 + 36 - 7 ) self.t( '(37 + n%6) - (23 + n%7)', 37 - 23 - 6, 37 + 5 - 23 ) def test_sub_overflow(self): self.t( '(23 - n%6) - (23 + n%6)', # no overflow for n=0 0, 0 ) self.t( '(23 + n%6) - (37 + n%7)', # always overflows None ) def test_mul(self): self.t( '(6 + n%37) * (7 + n%23)', 6 * 7, (6 + 37 - 1) * (7 + 23 - 1) ) def test_mul_max_overflow(self): m = (1 << 32) - 1 self.t('(n + 6) * 7', 42, m) def test_mul_min_overflow(self): m = (1 << 32) - 1 assert m % 17 == 0 self.t( str(m // 17) + ' * (n + 17)', m, m ) self.t( str(m // 17) + ' * (n + 18)', None ) self.t( str((m + 1) // 2) + ' * (n + 2)', None ) def test_div(self): self.t( '(42 + n%63) / (6 + n%7)', 42 // (6 + 7), (42 + 63 - 1) // 6, ) def test_not(self): self.t('! (n % 7)', 0, 1) self.t('! (6 + n % 7)', 0, 0) self.t('! 0', 1, 1) def r(self, x, y, *, var='n'): if x == y: s = str(x) else: w = y - x + 1 assert w >= 2 s = '{x} + ({var})%{w}'.format(x=x, w=w, var=var) self.t(s, x, y) return s def t_cmp(self, ccmp, pycmp): sl = '1 + n%3' for x in range(4): for y in range(x, 5): sr = self.r(x, y, var='n/3') s = '{l} {cmp} {r}'.format(l=sl, cmp=ccmp, r=sr) vals = { int(pycmp(i, j)) for i in range(1, 4) for j in range(x, y + 1) } self.t(s, min(vals), max(vals)) n = 42 s = '{l} {cmp} {r}'.format(l=n, cmp=ccmp, r=n) self.t(s, pycmp(n, n), pycmp(n, n)) def test_lt(self): self.t_cmp('<', int.__lt__) def test_le(self): self.t_cmp('<=', int.__le__) def test_gt(self): self.t_cmp('>', int.__gt__) def test_ge(self): self.t_cmp('>=', int.__ge__) def test_eq(self): self.t_cmp('==', int.__eq__) def test_ne(self): self.t_cmp('!=', int.__ne__) def t_bool(self, cop, pyop): ranges = [ (x, y) for x in range(0, 3) for y in range(x, 3) ] for lx, ly in ranges: sl = self.r(lx, ly, var='n%3') for rx, ry in ranges: sr = self.r(rx, ry, var='n/3') s = '{l} {op} {r}'.format(l=sl, op=cop, r=sr) vals = { int(pyop(i, j)) for i in range(lx, ly + 1) for j in range(rx, ry + 1) } self.t(s, min(vals), max(vals)) def test_and(self): def op_and(x, y): return bool(x and y) self.t_bool('&&', op_and) def test_and_error(self): self.t('n && (n / 0) && 0', 0, 0) # doesn't raise exception for n==0 self.t('1 && (n / 0) && 0', None) # always raises exception def test_or(self): def op_or(x, y): return bool(x or y) self.t_bool('||', op_or) def test_or_error(self): self.t('n || (n / 0) || 1', 1, 1) # doesn't raise exception for n>0 self.t('0 || (n / 0) || 1', None) # always raises exception def test_cond_error(self): self.t('(n / 0) ? 37 : 42', None) def test_cond_always_true(self): self.t('1 ? 37 : n', 37, 37) def test_cond_always_false(self): self.t('0 ? n : 37', 37, 37) def test_cond_true_branch_error(self): self.t('n ? (n / 0) : 37', 37, 37) def test_cond_false_branch_error(self): self.t('n ? 37 : (n / 0)', 37, 37) def test_cond_both_branches_error(self): self.t('n ? (n / 0) : (n / 0)', None) def test_cond_both_braches_ok(self): self.t('n ? 37 : 42', 37, 42) self.t( 'n ? (6 + n%23) : (7 + n%37)', 6, 37 + 7 - 1 ) class test_plural_forms: error = M.PluralFormsSyntaxError def t(self, s): return M.parse_plural_forms(s) def test_nplurals_0(self): with assert_raises(self.error): self.t('nplurals=0; plural=0;') def test_nplurals_positive(self): for i in 1, 2, 10, 42: self.t('nplurals={}; plural=0;'.format(i)) def test_missing_trailing_semicolon(self): self.t('nplurals=1; plural=0') class test_fix_date_format: def t(self, old, expected): if expected is None: with assert_raises(M.DateSyntaxError): M.fix_date_format(old) else: new = M.fix_date_format(old) assert_is_not_none(new) assert_equal(new, expected) def tbp(self, old): with assert_raises(M.BoilerplateDate): M.fix_date_format(old) def test_boilerplate(self): self.tbp('YEAR-MO-DA HO:MI+ZONE') self.tbp('YEAR-MO-DA HO:MI +ZONE') def test_partial_boilerplate(self): self.tbp('2000-05-15 22:MI+0200') self.tbp('2002-10-15 HO:MI+ZONE') self.tbp('2003-07-DA 11:31+0100') self.tbp('2004-MO-DA HO:MI+ZONE') self.tbp('2006-10-24 18:00+ZONE') self.tbp('2010-11-01 HO:MI+0000') def test_okay(self): d = '2010-10-13 01:27+0200' self.t(d, d) def test_double_space(self): d = '2011-11-08 16:49+0200' self.t(d, d.replace(' ', ' ')) def test_space_before_tz(self): self.t( '2010-05-12 18:36 -0400', '2010-05-12 18:36-0400', ) def test_seconds(self): self.t( '2010-03-27 12:44:19+0100', '2010-03-27 12:44+0100', ) def test_colon_in_tz(self): self.t( '2001-06-25 18:55+02:00', '2001-06-25 18:55+0200', ) def test_t_seperator(self): self.t( '2003-04-01T09:08+0500', '2003-04-01 09:08+0500', ) def test_missing_tz(self): self.t('2002-01-01 03:05', None) def test_tz_hint(self): assert_equal( M.fix_date_format('2002-01-01 03:05', tz_hint='+0900'), '2002-01-01 03:05+0900', ) def test_gmt_before_tz(self): self.t( '2001-07-28 11:19GMT+0200', '2001-07-28 11:19+0200', ) self.t( '2001-12-20 17:22UTC+0100', '2001-12-20 17:22+0100', ) def test_pygettext(self): self.t( '2004-04-20 13:24+CEST', '2004-04-20 13:24+0200', ) self.t('2004-04-14 21:35+CDT', None) # ambiguous self.t('2005-12-20 10:33+JEST', None) # nonexistent def test_abbrev(self): self.t( '2010-02-17 13:11 PST', '2010-02-17 13:11-0800', ) self.t( '2001-01-06 12:12GMT', '2001-01-06 12:12+0000', ) def test_only_date(self): self.t('2008-01-09', None) def test_nonexistent(self): self.t('2010-02-29 19:49+0200', None) class test_parse_date: t = staticmethod(M.parse_date) def test_nonexistent(self): with assert_raises(M.DateSyntaxError): self.t('2010-02-29 19:49+0200') def test_existent(self): d = self.t('2003-09-08 21:26+0200') assert_equal(d.second, 0) assert_is_instance(d, datetime.datetime) assert_equal(str(d), '2003-09-08 21:26:00+02:00') def test_epoch(self): d = self.t('2008-04-03 16:06+0300') assert_less(M.epoch, d) class test_string_formats: def test_nonempty(self): # XXX Update this number after editing data/string-formats: expected = 27 assert_equal(len(M.string_formats), expected) def test_lowercase(self): for s in M.string_formats: assert_is_instance(s, str) assert_true(s) assert_equal(s, s.lower()) # vim:ts=4 sw=4 et i18nspector-0.13.4/tests/test_encodings.py0000644000000000000000000002053712312562472020513 0ustar00rootroot00000000000000# Copyright © 2012, 2013, 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import curses.ascii import sys import nose from nose.tools import ( assert_equal, assert_false, assert_is_none, assert_not_in, assert_raises, assert_true, ) from . import aux import lib.encodings as E class test_is_portable_encoding: def test_found(self): assert_true(E.is_portable_encoding('ISO-8859-2')) def test_found_(self): assert_true(E.is_portable_encoding('ISO_8859-2')) def test_found_nonpython(self): assert_false(E.is_portable_encoding('KOI8-T')) assert_true(E.is_portable_encoding('KOI8-T', python=False)) def test_notfound(self): assert_false(E.is_portable_encoding('ISO-8859-16')) assert_false(E.is_portable_encoding('ISO-8859-16', python=False)) class test_propose_portable_encoding: def test_identity(self): encoding = 'ISO-8859-2' portable_encoding = E.propose_portable_encoding(encoding) assert_equal(portable_encoding, encoding) def test_found(self): def _test(encoding, expected_portable_encoding): portable_encoding = E.propose_portable_encoding(encoding) assert_equal(portable_encoding, expected_portable_encoding) yield _test, 'ISO8859-2', 'ISO-8859-2' yield _test, 'ISO_8859-2', 'ISO-8859-2' yield _test, 'Windows-1250', 'CP1250' def test_notfound(self): portable_encoding = E.propose_portable_encoding('ISO-8859-16') assert_is_none(portable_encoding) class test_ascii_compatiblity: def test_portable(self): def _test(encoding): assert_true(E.is_ascii_compatible_encoding(encoding)) assert_true(E.is_ascii_compatible_encoding(encoding, missing_ok=False)) for encoding in E.get_portable_encodings(): yield _test, encoding def test_incompatible(self): def _test(encoding): assert_false(E.is_ascii_compatible_encoding(encoding)) assert_false(E.is_ascii_compatible_encoding(encoding, missing_ok=False)) yield _test, 'UTF-7' yield _test, 'UTF-16' def _test_missing(self, encoding): assert_false(E.is_ascii_compatible_encoding(encoding)) with assert_raises(E.EncodingLookupError): E.is_ascii_compatible_encoding(encoding, missing_ok=False) def test_non_text(self): _test = self._test_missing yield _test, 'base64_codec' yield _test, 'bz2_codec' yield _test, 'hex_codec' yield _test, 'quopri_codec' yield _test, 'rot_13' yield _test, 'uu_codec' yield _test, 'zlib_codec' def test_missing(self): self._test_missing('eggs') class test_get_character_name: def test_latin(self): for i in range(ord('a'), ord('z')): u = chr(i) name = E.get_character_name(u) assert_equal(name, 'LATIN SMALL LETTER ' + u.upper()) u = chr(i).upper() name = E.get_character_name(u) assert_equal(name, 'LATIN CAPITAL LETTER ' + u) def test_c0(self): for i, curses_name in zip(range(0, 0x20), curses.ascii.controlnames): u = chr(i) name = E.get_character_name(u) expected_name = 'control character ' + curses_name assert_equal(name, expected_name) def test_del(self): name = E.get_character_name('\x7F') assert_equal(name, 'control character DEL') def test_c1(self): for i in range(0x80, 0xA0): u = chr(i) name = E.get_character_name(u) assert_true(name.startswith('control character ')) def test_uniqueness(self): names = set() for i in range(0, 0x100): u = chr(i) name = E.get_character_name(u) assert_not_in(name, names) names.add(name) def test_non_character(self): name = E.get_character_name('\uFFFE') assert_equal(name, 'non-character') name = E.get_character_name('\uFFFF') assert_equal(name, 'non-character') def test_lookup_error(self): with assert_raises(ValueError): E.get_character_name('\uE000') class test_extra_encoding: @aux.fork_isolation def test_install(self): encoding = 'VISCII' def enc(): ''.encode(encoding) def dec(): b'.'.decode(encoding) try: enc() except LookupError: pass else: raise nose.SkipTest( 'python{ver[0]}.{ver[1]} supports the {enc} encoding'.format( ver=sys.version_info, enc=encoding ) ) with assert_raises(LookupError): dec() E.install_extra_encodings() enc() dec() @aux.fork_isolation def test_8859(self): E.install_extra_encodings() encoding = '8859-2' portable_encoding = E.propose_portable_encoding(encoding) assert_equal('ISO-' + encoding, portable_encoding) @aux.fork_isolation def test_not_allowed(self): encoding = 'TSCII' def enc(): ''.encode(encoding) try: enc() except LookupError: pass else: raise nose.SkipTest( 'python{ver[0]}.{ver[1]} supports the {enc} encoding'.format( ver=sys.version_info, enc=encoding ) ) E.install_extra_encodings() with assert_raises(LookupError): enc() _viscii_unicode = 'Ti\u1EBFng Vi\u1EC7t' _viscii_bytes = b'Ti\xAAng Vi\xAEt' @aux.fork_isolation def test_8b_encode(self): E.install_extra_encodings() u = self._viscii_unicode b = u.encode('VISCII') assert_equal(b, self._viscii_bytes) @aux.fork_isolation def test_8b_encode_error(self): E.install_extra_encodings() u = self._viscii_unicode with assert_raises(UnicodeEncodeError): u.encode('KOI8-RU') @aux.fork_isolation def test_8b_decode(self): E.install_extra_encodings() b = self._viscii_bytes u = b.decode('VISCII') assert_equal(u, self._viscii_unicode) @aux.fork_isolation def test_8b_decode_error(self): E.install_extra_encodings() b = self._viscii_bytes with assert_raises(UnicodeDecodeError): b.decode('KOI8-T') _euc_tw_unicode = '\u4E2D\u6587' _euc_tw_bytes = b'\xC4\xE3\xC5\xC6' @aux.fork_isolation def test_mb_encode(self): E.install_extra_encodings() u = self._euc_tw_unicode b = u.encode('EUC-TW') assert_equal(b, self._euc_tw_bytes) @aux.fork_isolation def test_mb_encode_error(self): E.install_extra_encodings() u = self._viscii_unicode with assert_raises(UnicodeEncodeError): u.encode('EUC-TW') @aux.fork_isolation def test_mb_decode(self): E.install_extra_encodings() b = self._euc_tw_bytes u = b.decode('EUC-TW') assert_equal(u, self._euc_tw_unicode) @aux.fork_isolation def test_mb_decode_error(self): E.install_extra_encodings() b = self._viscii_bytes with assert_raises(UnicodeDecodeError): b.decode('EUC-TW') # vim:ts=4 sw=4 et i18nspector-0.13.4/tests/test_domains.py0000644000000000000000000000510012312562472020161 0ustar00rootroot00000000000000# Copyright © 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. from nose.tools import ( assert_false, assert_raises, assert_true, ) import lib.domains as M class test_domains: def t(self, domain, special=True): result = M.is_special_domain(domain) if special: assert_true(result) else: assert_false(result) def test_ok(self): self.t('test.jwilk.net', False) def test_in_addr_apra(self): self.t('119.216.184.93.in-addr.arpa') def test_ip6_arpa(self): self.t('7.a.a.0.7.9.0.1.7.4.4.1.f.b.6.2.d.6.0.0.0.2.2.0.0.0.8.2.6.0.6.2.ip6.arpa') def test_test(self): self.t('test') self.t('eggs.test') def test_localhost(self): self.t('localhost') self.t('eggs.localhost') def test_invalid(self): self.t('invalid') self.t('eggs.invalid') def test_example(self): self.t('example') for tld in 'com', 'net', 'org': self.t('example.{tld}'.format(tld=tld)) self.t('eggs.example.{tld}'.format(tld=tld)) class test_emails: def t(self, email, special=True): result = M.is_email_in_special_domain(email) if special: assert_true(result) else: assert_false(result) def test_valid(self): self.t('jwilk@test.jwilk.net', False) def test_special(self): self.t('jwilk@example.net') def test_no_at(self): with assert_raises(ValueError): self.t('jwilk%jwilk.net') # vim:ts=4 sw=4 et i18nspector-0.13.4/tests/run-tests0000755000000000000000000000252412312562472017017 0ustar00rootroot00000000000000#!/usr/bin/python3 # Copyright © 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import os import sys import nose sys.path[0] = os.path.join(os.path.dirname(__file__), '..') from tests import blackbox_tests if __name__ == '__main__': nose.main(addplugins=[blackbox_tests.Plugin()]) # vim:ts=4 sw=4 et i18nspector-0.13.4/tests/coverage.txt0000644000000000000000000000260512312562472017461 0ustar00rootroot00000000000000Generated automatically by private/update-line-coverage. Do not edit. Name Stmts Miss Cover Missing --------------------------------------------- lib 0 0 100% lib.checker 695 649 7% 75-79, 82-94, 98, 104-185, 189-320, 324-448, 453-524, 528-566, 571-603, 608-645, 648-723, 726-875, 880, 886, 893-899 lib.cli 103 77 25% 43-47, 55-64, 67-68, 71-73, 79-111, 114-122, 125-152 lib.domains 10 0 100% lib.encodings 130 39 70% 49-67, 79-87, 192-193, 200-212, 216-220 lib.gettext 140 0 100% lib.iconv 161 56 65% 41-42, 55-57, 64, 66, 68, 70, 77-78, 87-88, 101-102, 115-127, 134-135, 138-149, 155, 157, 159, 161, 170-171, 184-185, 202-217, 226-227, 230-241 lib.intexpr 256 0 100% lib.ling 243 3 99% 181, 272-273 lib.misc 57 0 100% lib.moparser 135 115 15% 47-71, 74, 77-82, 88-115, 118-182, 187-193, 196 lib.paths 7 2 71% 36-37 lib.polib4us 76 48 37% 39-40, 54, 70, 73-94, 98, 108-110, 131-143, 147, 159, 168-173 lib.tags 136 45 67% 45-49, 52-56, 59, 62, 107, 109, 112, 119-121, 131-132, 141-143, 148-150, 161, 172-179, 185-189, 199-212, 231, 234, 237 lib.terminal 48 19 60% 75-94 --------------------------------------------- TOTAL 2197 1053 52% i18nspector-0.13.4/tests/blackbox_tests/0000755000000000000000000000000012312562472020131 5ustar00rootroot00000000000000i18nspector-0.13.4/tests/blackbox_tests/zero-division-error-in-unused-plural-forms.po0000644000000000000000000000126012312562472030746 0ustar00rootroot00000000000000# W: arithmetic-error-in-unused-plural-forms f(2): division by zero msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%0<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/zero-division-error-in-plural-forms.po0000644000000000000000000000153612312562472027453 0ustar00rootroot00000000000000# E: arithmetic-error-in-plural-forms f(2): division by zero msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%0<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.13.4/tests/blackbox_tests/zero-bytes-file.po.tags0000644000000000000000000000075512312562472024455 0ustar00rootroot00000000000000P: no-language-header-field I: unable-to-determine-language P: no-mime-version-header-field MIME-Version: 1.0 P: no-content-transfer-encoding-header-field Content-Transfer-Encoding: 8bit E: no-content-type-header-field Content-Type: text/plain; charset= W: no-date-header-field POT-Creation-Date W: no-date-header-field PO-Revision-Date W: no-project-id-version-header-field W: no-report-msgid-bugs-to-header-field W: no-last-translator-header-field P: no-language-team-header-field i18nspector-0.13.4/tests/blackbox_tests/zero-bytes-file.po0000644000000000000000000000000012312562472023477 0ustar00rootroot00000000000000i18nspector-0.13.4/tests/blackbox_tests/zero-bytes-file.mo.tags0000644000000000000000000000004412312562472024441 0ustar00rootroot00000000000000E: invalid-mo-file unexpected magic i18nspector-0.13.4/tests/blackbox_tests/zero-bytes-file.mo0000644000000000000000000000000012312562472023474 0ustar00rootroot00000000000000i18nspector-0.13.4/tests/blackbox_tests/xfail-header-imitation.po0000644000000000000000000000136412312562472025021 0ustar00rootroot00000000000000# E: broken-encoding '<...>' cannot be decoded as ASCII # P: no-language-header-field # I: unable-to-determine-language # P: no-mime-version-header-field MIME-Version: 1.0 # P: no-content-transfer-encoding-header-field Content-Transfer-Encoding: 8bit # E: no-content-type-header-field Content-Type: text/plain; charset= # W: no-date-header-field POT-Creation-Date # W: no-date-header-field PO-Revision-Date # W: no-project-id-version-header-field # W: no-report-msgid-bugs-to-header-field # W: no-last-translator-header-field # P: no-language-team-header-field msgid "header imitation" msgstr "Content-Type: text/plain; charset=UTF-8" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis" i18nspector-0.13.4/tests/blackbox_tests/valid-range-flag.po0000644000000000000000000000146012312562472023572 0ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" #, range: 1..5 msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.13.4/tests/blackbox_tests/unusual-character-in-plural-translation.po0000644000000000000000000000156312312562472030361 0ustar00rootroot00000000000000# E: unusual-character-in-translation U+FFFF non-character: '<...> flag\uffff' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag￿" i18nspector-0.13.4/tests/blackbox_tests/unrepresentable-characters.po0000644000000000000000000000120312312562472026000 0ustar00rootroot00000000000000# E: unrepresentable-characters ISO-8859-1 <...> # E: unusual-character-in-translation U+00BF INVERTED QUESTION MARK: '<...>' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Mny bd, chro puk twj i sze flag." i18nspector-0.13.4/tests/blackbox_tests/unrepresentable-characters-euro.po0000644000000000000000000000130412312562472026752 0ustar00rootroot00000000000000# I: language-variant-does-not-affect-translation 'pl@euro' # E: unrepresentable-characters ISO-8859-1 <...> # E: unusual-character-in-translation U+00BF INVERTED QUESTION MARK: '<...>' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl@euro\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Mny bd, chro puk twj i sze flag." i18nspector-0.13.4/tests/blackbox_tests/unknown-poedit-language.po0000644000000000000000000000110412312562472025227 0ustar00rootroot00000000000000# I: unknown-poedit-language Latn msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Latn\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/unknown-message-flag.po0000644000000000000000000000114312312562472024520 0ustar00rootroot00000000000000# I: unknown-message-flag msgid 'A quick brown fox jumps over the lazy dog.': muzzy msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, muzzy msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/unknown-header-field.po0000644000000000000000000000111212312562472024472 0ustar00rootroot00000000000000# I: unknown-header-field Generator msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generator: pygettext.py 4.2\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/unknown-header-field-no-duplicate-hint.po0000644000000000000000000000126312312562472030023 0ustar00rootroot00000000000000# I: unknown-header-field POT-Revision-Date # Don't suggest renaming a field if such rename would lead to field # duplication. msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "POT-Revision-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/unknown-format-flag.po0000644000000000000000000000116712312562472024372 0ustar00rootroot00000000000000# I: unknown-message-flag msgid 'A quick brown fox jumps over the lazy dog.': intercal-format msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, intercal-format msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/unknown-file-type.pop0000644000000000000000000000105212312562472024242 0ustar00rootroot00000000000000# I: unknown-file-type msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." # vim:ft=po i18nspector-0.13.4/tests/blackbox_tests/unknown-encoding.po0000644000000000000000000000104412312562472023753 0ustar00rootroot00000000000000# E: unknown-encoding UTF-42 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-42\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/unexpected-flag-for-header-entry.po0000644000000000000000000000107512312562472026720 0ustar00rootroot00000000000000# W: unexpected-flag-for-header-entry blurry #, blurry msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/typoed-header-field-name.po0000644000000000000000000000116112312562472025221 0ustar00rootroot00000000000000# I: unknown-header-field MIME-Wersion => MIME-Version # P: no-mime-version-header-field MIME-Version: 1.0 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Wersion: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/typoed-flag-for-header-entry.po0000644000000000000000000000110412312562472026051 0ustar00rootroot00000000000000# W: unexpected-flag-for-header-entry muzzy => fuzzy #, muzzy msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/trailing-comment.po0000644000000000000000000000101512312562472023737 0ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." # oops i18nspector-0.13.4/tests/blackbox_tests/syntax-error.po0000644000000000000000000000077012312562472023152 0ustar00rootroot00000000000000# E: syntax-error-in-po-file line 16 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/syntax-error-in-unused-plural-expression.po0000644000000000000000000000151012312562472030542 0ustar00rootroot00000000000000# E: syntax-error-in-unused-plural-forms 'nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20 ? 1 : 2;' => 'nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20 ? 1 : 2;\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Mężny bądź, chroń pułk twój i sześć flag." i18nspector-0.13.4/tests/blackbox_tests/syntax-error-in-plural-expression.po0000644000000000000000000000176312312562472027253 0ustar00rootroot00000000000000# E: syntax-error-in-plural-forms 'nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20 ? 1 : 2;' => 'nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20 ? 1 : 2;\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.13.4/tests/blackbox_tests/stray-header-line-3.po0000644000000000000000000000115412312562472024147 0ustar00rootroot00000000000000# E: stray-header-line 'Project-Id-Version Gizmo Enhancer 1.0' # W: no-project-id-version-header-field msgid "" msgstr "" "Project-Id-Version Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/stray-header-line-2.po0000644000000000000000000000116212312562472024145 0ustar00rootroot00000000000000# E: stray-header-line 'POT-Creation-Date 2012-11-01 14:42+0100' # W: no-date-header-field POT-Creation-Date msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/stray-header-line-1.po0000644000000000000000000000114312312562472024143 0ustar00rootroot00000000000000# E: stray-header-line 'MIME-Version 1.0' # P: no-mime-version-header-field MIME-Version: 1.0 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/seemingly-duplicate-message-definition.po0000644000000000000000000000120312312562472030201 0ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." msgctxt "rot13" msgid "A quick brown fox jumps over the lazy dog." msgstr "Fvp shtvraf, qhk, mrybglcbf, dhnz Xnehf unorevf." i18nspector-0.13.4/tests/blackbox_tests/rfc2606-in-report-msgid-bugs-to.po0000644000000000000000000000110612312562472026153 0ustar00rootroot00000000000000# W: invalid-report-msgid-bugs-to 'gizmoenhancer@example.org' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@example.org\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/rfc2606-in-last-translator.po0000644000000000000000000000110612312562472025313 0ustar00rootroot00000000000000# W: invalid-last-translator 'Jakub Wilk ' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/rfc2606-in-language-team.po0000644000000000000000000000107712312562472024677 0ustar00rootroot00000000000000# W: invalid-language-team 'Latin ' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/redundant-message-flag-2.po0000644000000000000000000000131212312562472025142 0ustar00rootroot00000000000000# P: redundant-message-flag msgid 'A quick brown fox jumps over the lazy dog.': no-python-brace-format no-python-format (implied by c-format) msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, c-format, no-python-format, no-python-brace-format msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/redundant-message-flag-1.po0000644000000000000000000000123512312562472025145 0ustar00rootroot00000000000000# P: redundant-message-flag msgid 'A quick brown fox jumps over the lazy dog.': possible-c-format (implied by c-format) msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, c-format, possible-c-format msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/range-flag-without-plural-string.po0000644000000000000000000000107312312562472026777 0ustar00rootroot00000000000000# W: range-flag-without-plural-string msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, range: 1..5 msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/publican-dates.po0000644000000000000000000000141612312562472023366 0ustar00rootroot00000000000000# E: invalid-content-type 'application/x-publican; charset=UTF-8' => 'text/plain; charset=UTF-8' # W: invalid-date POT-Creation-Date: '2012-11-01T13:42' => '2012-11-01 13:42+0000' # W: invalid-date PO-Revision-Date: '2012-11-01T13:42' => '2012-11-01 13:42+0000' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01T13:42\n" "PO-Revision-Date: 2012-11-01T13:42\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: application/x-publican; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/plural-forms-without-plural-expression.po0000644000000000000000000000151512312562472030311 0ustar00rootroot00000000000000# E: syntax-error-in-plural-forms 3 => 'nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: 3\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.13.4/tests/blackbox_tests/plural-forms-okay.pot0000644000000000000000000000112712312562472024242 0ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.13.4/tests/blackbox_tests/plural-forms-okay.po0000644000000000000000000000144112312562472024055 0ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.13.4/tests/blackbox_tests/okay.pot0000644000000000000000000000073612312562472021626 0ustar00rootroot00000000000000#, fuzzy msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "" i18nspector-0.13.4/tests/blackbox_tests/okay.po0000644000000000000000000000100512312562472021430 0ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/okay-little-endian.mo.gen0000755000000000000000000000012412312562472024730 0ustar00rootroot00000000000000#!/bin/sh set -e -u -x exec msgfmt --endian=little "${here}/okay.po" -o "${target}" i18nspector-0.13.4/tests/blackbox_tests/okay-little-endian.mo0000644000000000000000000000101212312562472024152 0ustar00rootroot00000000000000,<P*Q\|0A quick brown fox jumps over the lazy dog.Project-Id-Version: Gizmo Enhancer 1.0 Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net POT-Creation-Date: 2012-11-01 14:42+0100 PO-Revision-Date: 2012-11-01 14:42+0100 Last-Translator: Jakub Wilk Language-Team: Latin Language: la MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sic fugiens, dux, zelotypos, quam Karus haberis.i18nspector-0.13.4/tests/blackbox_tests/okay-big-endian.mo.gen0000755000000000000000000000012112312562472024171 0ustar00rootroot00000000000000#!/bin/sh set -e -u -x exec msgfmt --endian=big "${here}/okay.po" -o "${target}" i18nspector-0.13.4/tests/blackbox_tests/okay-big-endian.mo0000644000000000000000000000101212312562472023416 0ustar00rootroot00000000000000,<P*Q\|0A quick brown fox jumps over the lazy dog.Project-Id-Version: Gizmo Enhancer 1.0 Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net POT-Creation-Date: 2012-11-01 14:42+0100 PO-Revision-Date: 2012-11-01 14:42+0100 Last-Translator: Jakub Wilk Language-Team: Latin Language: la MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sic fugiens, dux, zelotypos, quam Karus haberis.i18nspector-0.13.4/tests/blackbox_tests/nonexistent-language.po0000644000000000000000000000110112312562472024621 0ustar00rootroot00000000000000# E: invalid-language ry # I: unable-to-determine-language msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: ry\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/non-text-encoding.po0000644000000000000000000000105412312562472024031 0ustar00rootroot00000000000000# E: unknown-encoding zlib_codec msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=zlib_codec\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/non-python-portable-encoding.po0000644000000000000000000000075512312562472026203 0ustar00rootroot00000000000000# E: non-portable-encoding GEORGIAN-PS msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Georgian \n" "Language: ka\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=GEORGIAN-PS\n" "Content-Transfer-Encoding: 8bit\n" msgid "Georgia" msgstr "" i18nspector-0.13.4/tests/blackbox_tests/non-python-encoding.po0000644000000000000000000000111312312562472024362 0ustar00rootroot00000000000000# E: non-portable-encoding KOI8-RU msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Ukrainian \n" "Language: uk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=KOI8-RU\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr " Ʀ ަ, Τ ' ." i18nspector-0.13.4/tests/blackbox_tests/non-portable-encoding.po0000644000000000000000000000106312312562472024655 0ustar00rootroot00000000000000# E: non-portable-encoding ISO-8859-16 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-16\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/non-portable-encoding-with-hint.po0000644000000000000000000000107712312562472026573 0ustar00rootroot00000000000000# E: non-portable-encoding Windows-1252 => CP1252 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=Windows-1252\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/non-ascii-project-id.po0000644000000000000000000000102212312562472024402 0ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Гизмо Энханцэр 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/non-ascii-compatible.po0000644000000000000000000000105712312562472024471 0ustar00rootroot00000000000000# E: non-ascii-compatible-encoding UTF-7 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-7\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/no-version-in-project-id-version.po0000644000000000000000000000107112312562472026714 0ustar00rootroot00000000000000# P: no-version-in-project-id-version 'Gizmo Enhancer' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/no-required-plural-forms.po0000644000000000000000000000147512312562472025353 0ustar00rootroot00000000000000# E: no-required-plural-forms-header-field 'nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.13.4/tests/blackbox_tests/no-report-msgid-bugs.po0000644000000000000000000000077612312562472024467 0ustar00rootroot00000000000000# W: no-report-msgid-bugs-to-header-field msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/no-project-id-version.po0000644000000000000000000000100312312562472024620 0ustar00rootroot00000000000000# W: no-project-id-version-header-field msgid "" msgstr "" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/no-pot-creation-date.po0000644000000000000000000000100512312562472024416 0ustar00rootroot00000000000000# W: no-date-header-field POT-Creation-Date msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/no-po-revision-date.po0000644000000000000000000000100512312562472024264 0ustar00rootroot00000000000000# W: no-date-header-field PO-Revision-Date msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/no-plural-forms.pot0000644000000000000000000000115212312562472023711 0ustar00rootroot00000000000000# W: no-plural-forms-header-field 'nplurals=INTEGER; plural=EXPRESSION;' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.13.4/tests/blackbox_tests/no-plural-forms.po0000644000000000000000000000125212312562472023526 0ustar00rootroot00000000000000# W: no-plural-forms-header-field 'nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" msgstr[2] "" i18nspector-0.13.4/tests/blackbox_tests/no-package-name-in-project-id-version.po0000644000000000000000000000104612312562472027542 0ustar00rootroot00000000000000# I: no-package-name-in-project-id-version 1.0 msgid "" msgstr "" "Project-Id-Version: 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/no-mime-version.po0000644000000000000000000000104412312562472023514 0ustar00rootroot00000000000000# P: no-mime-version-header-field MIME-Version: 1.0 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/no-last-translator.po0000644000000000000000000000077112312562472024242 0ustar00rootroot00000000000000# W: no-last-translator-header-field msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/no-language-team.po0000644000000000000000000000100412312562472023605 0ustar00rootroot00000000000000# P: no-language-team-header-field msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/no-language-header-field.po0000644000000000000000000000106512312562472025177 0ustar00rootroot00000000000000# P: no-language-header-field # I: unable-to-determine-language msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/no-language-header-field-with-hint.po0000644000000000000000000000106012312562472027103 0ustar00rootroot00000000000000# --language=la # P: no-language-header-field Language: la msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/no-content-type.po0000644000000000000000000000105112312562472023531 0ustar00rootroot00000000000000# E: no-content-type-header-field Content-Type: text/plain; charset= msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/no-content-transfer-encoding.po0000644000000000000000000000106112312562472026161 0ustar00rootroot00000000000000# P: no-content-transfer-encoding-header-field Content-Transfer-Encoding: 8bit msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/next-line-control-character-in-translation.po0000644000000000000000000000122012312562472030737 0ustar00rootroot00000000000000# E: unrepresentable-characters ISO-8859-1 <...> # E: unusual-character-in-translation <...>, U+0085 control character NEL, <...> msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Mężny bądź, chroń pułk twój i sześć flag." i18nspector-0.13.4/tests/blackbox_tests/next-line-control-character-in-header-entry.po0000644000000000000000000000112012312562472030767 0ustar00rootroot00000000000000# E: unusual-character-in-header-entry U+0085 control character NEL msgid "" msgstr "" "Project-Id-Version: Gizmo Enhąncer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/message-flags-splitting-2.po0000644000000000000000000000102112312562472025353 0ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, fuzzy msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis.\n" i18nspector-0.13.4/tests/blackbox_tests/message-flags-splitting-1.po0000644000000000000000000000103412312562472025356 0ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, no-c-format,fuzzy msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis.\n" i18nspector-0.13.4/tests/blackbox_tests/lowercase-header-field-name.po0000644000000000000000000000116112312562472025701 0ustar00rootroot00000000000000# I: unknown-header-field Mime-Version => MIME-Version # P: no-mime-version-header-field MIME-Version: 1.0 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "Mime-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/lexer-error-in-plural-expression.po0000644000000000000000000000176312312562472027044 0ustar00rootroot00000000000000# E: syntax-error-in-plural-forms 'nplurals=3; plural=n==1 ? 0 : n%10>=2 & n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;' => 'nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 & n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.13.4/tests/blackbox_tests/language-variant-does-not-affect-translation.po0000644000000000000000000000110712312562472031225 0ustar00rootroot00000000000000# I: language-variant-does-not-affect-translation 'la@euro' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la@euro\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/language-variant-does-affect-translation.po0000644000000000000000000000101212312562472030422 0ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la@quot\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/language-team-equal-to-last-translator.po0000644000000000000000000000116112312562472030054 0ustar00rootroot00000000000000# I: language-team-equal-to-last-translator 'Latin ' 'Jakub Wilk ' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/language-disparity-poedit.po0000644000000000000000000000117512312562472025550 0ustar00rootroot00000000000000# W: language-disparity la (Language header field) != el (X-Poedit-Language header field) msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Greek\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/language-disparity-command-line.po0000644000000000000000000000113612312562472026624 0ustar00rootroot00000000000000# --language el # W: language-disparity el (command-line) != la (Language header field) msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/invalid-report-msgid-bugs.po0000644000000000000000000000112212312562472025463 0ustar00rootroot00000000000000# W: invalid-report-msgid-bugs-to 'Gizmo Enhancer Development Team' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: Gizmo Enhancer Development Team\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/invalid-range-flag.po0000644000000000000000000000161212312562472024120 0ustar00rootroot00000000000000# E: invalid-range-flag msgid '%d quick brown fox jumps over the lazy dog.': 'range: 1-5' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" #, range: 1-5 msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.13.4/tests/blackbox_tests/invalid-range-flag-empty.po0000644000000000000000000000161412312562472025256 0ustar00rootroot00000000000000# E: invalid-range-flag msgid '%d quick brown fox jumps over the lazy dog.': 'range: 2..1' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" #, range: 2..1 msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.13.4/tests/blackbox_tests/invalid-range-flag-1-element.po0000644000000000000000000000161412312562472025707 0ustar00rootroot00000000000000# E: invalid-range-flag msgid '%d quick brown fox jumps over the lazy dog.': 'range: 1..1' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" #, range: 1..1 msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.13.4/tests/blackbox_tests/invalid-pot-creation-date.po0000644000000000000000000000105312312562472025433 0ustar00rootroot00000000000000# W: invalid-date POT-Creation-Date: 2012-11-01 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/invalid-pot-creation-date-with-hint.po0000644000000000000000000000114012312562472027341 0ustar00rootroot00000000000000# W: invalid-date POT-Creation-Date: '2012-11-01 14:42+01:00' => '2012-11-01 14:42+0100' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+01:00\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/invalid-po-revision-date.po0000644000000000000000000000105212312562472025300 0ustar00rootroot00000000000000# W: invalid-date PO-Revision-Date: 2012-11-01 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/invalid-po-revision-date-with-hint.po0000644000000000000000000000113712312562472027215 0ustar00rootroot00000000000000# W: invalid-date PO-Revision-Date: '2012-11-01 14:42+01:00' => '2012-11-01 14:42+0100' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+01:00\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/invalid-mo-file.mo0000644000000000000000000000107112312562472023441 0ustar00rootroot00000000000000# E: invalid-mo-file unexpected magic msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." # vim:ft=po i18nspector-0.13.4/tests/blackbox_tests/invalid-mime-version.po0000644000000000000000000000105312312562472024526 0ustar00rootroot00000000000000# P: invalid-mime-version 4.2 => 1.0 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 4.2\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/invalid-last-translator.po0000644000000000000000000000103612312562472025247 0ustar00rootroot00000000000000# W: invalid-last-translator 'Jakub Wilk' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk\n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/invalid-language.po0000644000000000000000000000110112312562472023671 0ustar00rootroot00000000000000# E: invalid-language LA # I: unable-to-determine-language msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: LA\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/invalid-language-natural-name.po0000644000000000000000000000105312312562472026261 0ustar00rootroot00000000000000# E: invalid-language Latin => la msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: Latin\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/invalid-language-corrected.po0000644000000000000000000000104712312562472025652 0ustar00rootroot00000000000000# E: invalid-language lat => la msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: lat\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/invalid-content-type.po0000644000000000000000000000110212312562472024540 0ustar00rootroot00000000000000# E: invalid-content-type 'text/plain' => 'text/plain; charset=' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/invalid-content-type-with-hint.po0000644000000000000000000000114112312562472026454 0ustar00rootroot00000000000000# E: invalid-content-type 'text/enriched; charset=UTF-8' => 'text/plain; charset=UTF-8' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/enriched; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/invalid-content-transfer-encoding.po0000644000000000000000000000107412312562472027177 0ustar00rootroot00000000000000# P: invalid-content-transfer-encoding 42bit => 8bit msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 42bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/integer-overflow-in-unused-plural-forms.po0000644000000000000000000000126612312562472030322 0ustar00rootroot00000000000000# W: arithmetic-error-in-unused-plural-forms f(12): integer overflow msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%(0-100)>=20) ? 1 : 2;\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/integer-overflow-in-plural-forms.po0000644000000000000000000000154412312562472027020 0ustar00rootroot00000000000000# E: arithmetic-error-in-plural-forms f(12): integer overflow msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%(0-100)>=20) ? 1 : 2;\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.13.4/tests/blackbox_tests/incorrect-unused-plural-forms.po0000644000000000000000000000132012312562472026377 0ustar00rootroot00000000000000# W: incorrect-unused-plural-forms 'nplurals=2; plural=n != 1;' => 'nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\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 "A quick brown fox jumps over the lazy dog." msgstr "Mężny bądź, chroń pułk twój i sześć flag." i18nspector-0.13.4/tests/blackbox_tests/incorrect-plural-forms.po0000644000000000000000000000150112312562472025077 0ustar00rootroot00000000000000# E: incorrect-plural-forms 'nplurals=2; plural=n != 1;' => 'nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\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 "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." i18nspector-0.13.4/tests/blackbox_tests/incorrect-number-of-plural-forms.po0000644000000000000000000000151212312562472026771 0ustar00rootroot00000000000000# E: incorrect-number-of-plural-forms 3 (Plural-Forms header field) != 2 (number of msgstr items) msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." i18nspector-0.13.4/tests/blackbox_tests/inconsistent-trailing-newlines.po0000644000000000000000000000114012312562472026636 0ustar00rootroot00000000000000# E: inconsistent-leading-newlines msgid '\nA quick brown fox jumps over the lazy dog.' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "\nA quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/inconsistent-trailing-newlines-fuzzy.po0000644000000000000000000000102012312562472030020 0ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, fuzzy msgid "\nA quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/inconsistent-number-of-plural-forms.po0000644000000000000000000000234212312562472027523 0ustar00rootroot00000000000000# E: inconsistent-number-of-plural-forms 2 (msgid '%d quick brown fox jumps over the lazy dog.' msgctxt 'missing plural form') != 3 (msgid '%d quick brown fox jumps over the lazy dog.') msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." msgctxt "missing plural form" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." i18nspector-0.13.4/tests/blackbox_tests/inconsistent-leading-newlines.po0000644000000000000000000000113712312562472026436 0ustar00rootroot00000000000000# E: inconsistent-trailing-newlines msgid 'A quick brown fox jumps over the lazy dog.' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis.\n" i18nspector-0.13.4/tests/blackbox_tests/inconsistent-leading-newlines-fuzzy.po0000644000000000000000000000102012312562472027612 0ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, fuzzy msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis.\n" i18nspector-0.13.4/tests/blackbox_tests/header-imitation.mo.gen0000755000000000000000000000115212312562472024463 0ustar00rootroot00000000000000#!/bin/sh # P: no-language-header-field # I: unable-to-determine-language # P: no-mime-version-header-field MIME-Version: 1.0 # P: no-content-transfer-encoding-header-field Content-Transfer-Encoding: 8bit # E: no-content-type-header-field Content-Type: text/plain; charset= # W: no-date-header-field POT-Creation-Date # W: no-date-header-field PO-Revision-Date # W: no-project-id-version-header-field # W: no-report-msgid-bugs-to-header-field # W: no-last-translator-header-field # P: no-language-team-header-field set -e -u -x exec msgfmt --endian=little "${here}/xfail-header-imitation.po" -o "${target}" i18nspector-0.13.4/tests/blackbox_tests/header-imitation.mo0000644000000000000000000000034612312562472023714 0ustar00rootroot00000000000000,<*P{0(A quick brown fox jumps over the lazy dog.header imitationSic fugiens, dux, zelotypos, quam Karus haberis.Content-Type: text/plain; charset=UTF-16i18nspector-0.13.4/tests/blackbox_tests/header-entry-flags-splitting.po0000644000000000000000000000114512312562472026166 0ustar00rootroot00000000000000# P: fuzzy-header-entry # W: unexpected-flag-for-header-entry no-c-format #, no-c-format,fuzzy msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/hash-only-comment.po0000644000000000000000000000101412312562472024027 0ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #oops msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/generated-by-field.po0000644000000000000000000000162412312562472024123 0ustar00rootroot00000000000000# The Generated-By field is not not used or generated by any of the GNU # gettext tools. Nevertheless it's rather widespead, as it's used by # pygettext[0] and Babel[1]. Emitting unknown-header-field would be # counter-productive. # # [0] http://docs.python.org/3/library/gettext.html#internationalizing-your-programs-and-modules # [1] http://babel.edgewall.org/ msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 4.2\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/fuzzy-header-entry.po0000644000000000000000000000104712312562472024247 0ustar00rootroot00000000000000# P: fuzzy-header-entry #, fuzzy msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/future-pot-creation-date.po0000644000000000000000000000110712312562472025317 0ustar00rootroot00000000000000# W: date-from-future POT-Creation-Date: '2142-04-02 03:37+0100' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2142-04-02 03:37+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/future-po-revision-date.po0000644000000000000000000000110612312562472025164 0ustar00rootroot00000000000000# W: date-from-future PO-Revision-Date: '2142-04-02 03:37+0100' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2142-04-02 03:37+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/escape-sequences.po0000644000000000000000000000115512312562472023724 0ustar00rootroot00000000000000# E: duplicate-message-definition msgid '\x07\x07\x08\x08\x0c\x0c\t\t\x0b\x0b\r\u2026\n' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "\a\7\b\x8\f\x0c\t\11\v\013\r\xE2\x80\246\n" msgstr "" msgid "\a\7\b\x8\f\x0c\t\11\v\013\r\342\200\xA6\n" msgstr "" i18nspector-0.13.4/tests/blackbox_tests/encoding-in-header-field.po0000644000000000000000000000107412312562472025174 0ustar00rootroot00000000000000# W: encoding-in-language-header-field la.UTF-8 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la.UTF-8\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/empty-report-msgid-bugs.po0000644000000000000000000000103112312562472025172 0ustar00rootroot00000000000000# W: no-report-msgid-bugs-to-header-field msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/empty-project-id-version.po0000644000000000000000000000114312312562472025347 0ustar00rootroot00000000000000# I: no-package-name-in-project-id-version (empty string) # P: no-version-in-project-id-version (empty string) msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/empty-pot-creation-date.po0000644000000000000000000000104512312562472025144 0ustar00rootroot00000000000000# W: invalid-date POT-Creation-Date: (empty string) msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: \n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/empty-po-revision-date.po0000644000000000000000000000104412312562472025011 0ustar00rootroot00000000000000# W: invalid-date PO-Revision-Date: (empty string) msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: \n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/empty-msgid-message-with-source-code-references.po0000644000000000000000000000112412312562472031646 0ustar00rootroot00000000000000# E: empty-msgid-message-with-source-code-references 'gizmo.c:1' #: gizmo.c:1 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/empty-msgid-message-with-plural-forms.po0000644000000000000000000000157212312562472027751 0ustar00rootroot00000000000000# E: empty-msgid-message-with-plural-forms msgid "" msgid_plural "" msgstr[0] "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" msgstr[1] "" msgstr[2] "" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.13.4/tests/blackbox_tests/empty-mime-version.po0000644000000000000000000000106312312562472024237 0ustar00rootroot00000000000000# P: invalid-mime-version (empty string) => 1.0 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: \n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/empty-file.po0000644000000000000000000000065112312562472022546 0ustar00rootroot00000000000000# W: empty-file msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" i18nspector-0.13.4/tests/blackbox_tests/empty-content-type.po0000644000000000000000000000107212312562472024256 0ustar00rootroot00000000000000# E: invalid-content-type (empty string) => 'text/plain; charset=' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: \n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/empty-content-transfer-encoding.po0000644000000000000000000000110012312562472026675 0ustar00rootroot00000000000000# P: invalid-content-transfer-encoding (empty string) => 8bit msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-message-flag.po0000644000000000000000000000117612312562472025001 0ustar00rootroot00000000000000# W: duplicate-message-flag msgid 'A quick brown fox jumps over the lazy dog.': no-c-format msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, no-c-format, no-c-format msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-message-definition.po0000644000000000000000000000131112312562472026207 0ustar00rootroot00000000000000# E: duplicate-message-definition msgid 'A quick brown fox jumps over the lazy dog.' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-message-definition-with-context.po0000644000000000000000000000136712312562472030655 0ustar00rootroot00000000000000# E: duplicate-message-definition msgid 'A quick brown fox jumps over the lazy dog.' msgctxt rot13 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgctxt "rot13" msgid "A quick brown fox jumps over the lazy dog." msgstr "Fvp shtvraf, qhk, mrybglcbf, dhnz Xnehf unorevf." msgctxt "rot13" msgid "A quick brown fox jumps over the lazy dog." msgstr "Fvp shtvraf, qhk, mrybglcbf, dhnz Xnehf unorevf." i18nspector-0.13.4/tests/blackbox_tests/duplicate-header-field.po0000644000000000000000000000114312312562472024751 0ustar00rootroot00000000000000# I: duplicate-header-field Generated-By msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: VIM 7.3\n" "Generated-By: VIM 7.3\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-header-field-x-poedit-language.po0000644000000000000000000000116712312562472030267 0ustar00rootroot00000000000000# W: duplicate-header-field-x-poedit X-Poedit-Language msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Latin\n" "X-Poedit-Language: Latin\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-header-field-x-poedit-country.po0000644000000000000000000000116612312562472030206 0ustar00rootroot00000000000000# W: duplicate-header-field-x-poedit X-Poedit-Country msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Country: Poland\n" "X-Poedit-Country: Poland\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-header-field-report-msgid-bugs-to.po0000644000000000000000000000115112312562472030740 0ustar00rootroot00000000000000# W: duplicate-header-field-report-msgid-bugs-to msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-header-field-project-id-version.po0000644000000000000000000000114012312562472030467 0ustar00rootroot00000000000000# W: duplicate-header-field-project-id-version msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-header-field-pot-creation-date.po0000644000000000000000000000114612312562472030271 0ustar00rootroot00000000000000# W: duplicate-header-field-date POT-Creation-Date msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-header-field-po-revision-date.po0000644000000000000000000000114412312562472030135 0ustar00rootroot00000000000000# W: duplicate-header-field-date PO-Revision-Date msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-header-field-plural-forms.po0000644000000000000000000000166212312562472027400 0ustar00rootroot00000000000000# E: duplicate-header-field-plural-forms msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.13.4/tests/blackbox_tests/duplicate-header-field-mime-version.po0000644000000000000000000000110512312562472027357 0ustar00rootroot00000000000000# P: duplicate-header-field-mime-version msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-header-field-last-translator.po0000644000000000000000000000114412312562472030102 0ustar00rootroot00000000000000# W: duplicate-header-field-last-translator msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-header-field-language.po0000644000000000000000000000107412312562472026535 0ustar00rootroot00000000000000# E: duplicate-header-field-language msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-header-field-language-team.po0000644000000000000000000000112512312562472027456 0ustar00rootroot00000000000000# W: duplicate-header-field-language-team msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-header-field-content-type.po0000644000000000000000000000113312312562472027377 0ustar00rootroot00000000000000# E: duplicate-header-field-content-type msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-header-field-content-transfer-encoding.po0000644000000000000000000000114012312562472032024 0ustar00rootroot00000000000000# P: duplicate-header-field-content-transfer-encoding msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-header-entry.po0000644000000000000000000000167212312562472025036 0ustar00rootroot00000000000000# E: duplicate-header-entry msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-flag-for-header-entry.pot0000644000000000000000000000110112312562472026700 0ustar00rootroot00000000000000# W: duplicate-flag-for-header-entry fuzzy #, fuzzy, fuzzy msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/duplicate-empty-flag.po0000644000000000000000000000116412312562472024510 0ustar00rootroot00000000000000# I: unknown-message-flag msgid 'A quick brown fox jumps over the lazy dog.': (empty string) msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, ,no-c-format, msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/distant-header-entry.po0000644000000000000000000000104012312562472024517 0ustar00rootroot00000000000000# E: distant-header-entry msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" i18nspector-0.13.4/tests/blackbox_tests/crlf.po0000644000000000000000000000102412312562472021414 0ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/coverage.txt0000644000000000000000000000566212312562472022476 0ustar00rootroot00000000000000Generated automatically by private/update-tag-coverage. Do not edit. [X] ancient-date [X] arithmetic-error-in-plural-forms [X] arithmetic-error-in-unused-plural-forms [X] boilerplate-in-content-type [X] boilerplate-in-date [X] boilerplate-in-language-team [X] boilerplate-in-last-translator [X] boilerplate-in-project-id-version [X] boilerplate-in-report-msgid-bugs-to [X] broken-encoding [X] codomain-error-in-plural-forms [X] codomain-error-in-unused-plural-forms [X] conflict-marker-in-header-entry [X] conflict-marker-in-translation [X] conflicting-message-flags [X] date-from-future [X] distant-header-entry [X] duplicate-flag-for-header-entry [X] duplicate-header-entry [X] duplicate-header-field [X] duplicate-header-field-content-transfer-encoding [X] duplicate-header-field-content-type [X] duplicate-header-field-date [X] duplicate-header-field-language [X] duplicate-header-field-language-team [X] duplicate-header-field-last-translator [X] duplicate-header-field-mime-version [X] duplicate-header-field-plural-forms [X] duplicate-header-field-project-id-version [X] duplicate-header-field-report-msgid-bugs-to [X] duplicate-header-field-x-poedit [X] duplicate-message-definition [X] duplicate-message-flag [X] empty-file [X] empty-msgid-message-with-plural-forms [X] empty-msgid-message-with-source-code-references [X] encoding-in-language-header-field [X] fuzzy-header-entry [X] inconsistent-leading-newlines [X] inconsistent-number-of-plural-forms [X] inconsistent-trailing-newlines [X] incorrect-number-of-plural-forms [X] incorrect-plural-forms [X] incorrect-unused-plural-forms [X] invalid-content-transfer-encoding [X] invalid-content-type [X] invalid-date [X] invalid-language [X] invalid-language-team [X] invalid-last-translator [X] invalid-mime-version [X] invalid-mo-file [X] invalid-range-flag [X] invalid-report-msgid-bugs-to [X] language-disparity [X] language-team-equal-to-last-translator [X] language-variant-does-not-affect-translation [X] no-content-transfer-encoding-header-field [X] no-content-type-header-field [X] no-date-header-field [X] no-language-header-field [X] no-language-team-header-field [X] no-last-translator-header-field [X] no-mime-version-header-field [X] no-package-name-in-project-id-version [X] no-plural-forms-header-field [X] no-project-id-version-header-field [X] no-report-msgid-bugs-to-header-field [X] no-required-plural-forms-header-field [X] no-version-in-project-id-version [X] non-ascii-compatible-encoding [X] non-portable-encoding [X] os-error [X] range-flag-without-plural-string [X] redundant-message-flag [X] stray-header-line [X] syntax-error-in-plural-forms [X] syntax-error-in-po-file [X] syntax-error-in-unused-plural-forms [X] unable-to-determine-language [X] unexpected-flag-for-header-entry [X] unknown-encoding [X] unknown-file-type [X] unknown-header-field [X] unknown-message-flag [X] unknown-poedit-language [X] unrepresentable-characters [X] unusual-character-in-header-entry [X] unusual-character-in-translation i18nspector-0.13.4/tests/blackbox_tests/conflicting-message-flags.po0000644000000000000000000000116712312562472025511 0ustar00rootroot00000000000000# E: conflicting-message-flags msgid 'A quick brown fox jumps over the lazy dog.': wrap no-wrap msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, wrap, no-wrap msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/conflicting-format-flags-4.po0000644000000000000000000000125112312562472025510 0ustar00rootroot00000000000000# E: conflicting-message-flags msgid 'A quick brown fox jumps over the lazy dog.': possible-c-format impossible-c-format msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, possible-c-format, impossible-c-format msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/conflicting-format-flags-3.po0000644000000000000000000000122712312562472025512 0ustar00rootroot00000000000000# E: conflicting-message-flags msgid 'A quick brown fox jumps over the lazy dog.': c-format impossible-c-format msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, impossible-c-format, c-format msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/conflicting-format-flags-2.po0000644000000000000000000000120712312562472025507 0ustar00rootroot00000000000000# E: conflicting-message-flags msgid 'A quick brown fox jumps over the lazy dog.': c-format no-c-format msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, no-c-format, c-format msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/conflicting-format-flags-1.po0000644000000000000000000000121312312562472025503 0ustar00rootroot00000000000000# E: conflicting-message-flags msgid 'A quick brown fox jumps over the lazy dog.': c-format python-format msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #, c-format, python-format msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/conflict-marker-in-translation.po0000644000000000000000000000146412312562472026516 0ustar00rootroot00000000000000# E: conflict-marker-in-translation msgid 'A quick brown fox jumps over the lazy dog.' '#-#-#-#-# la.po (Gizmo Enhancer 1.0) #-#-#-#-#' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "" "#-#-#-#-# la.po (Gizmo Enhancer 1.0) #-#-#-#-#\n" "Sic fugiens, dux, zelotypos, quam Karus haberis.\n" "#-#-#-#-# pl.po (Gizmo Enhancer 1.0) #-#-#-#-#\n" "Mężny bądź, chroń pułk twój i sześć flag." i18nspector-0.13.4/tests/blackbox_tests/conflict-marker-in-header-entry-2.po0000644000000000000000000000122312312562472026677 0ustar00rootroot00000000000000# E: conflict-marker-in-header-entry '#-#-#-#-# la.po (Gizmo Enhancer 1.0) #-#-#-#-#' msgid "" msgstr "" "#-#-#-#-# la.po (Gizmo Enhancer 1.0) #-#-#-#-#\n" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/conflict-marker-in-header-entry-1.po0000644000000000000000000000122312312562472026676 0ustar00rootroot00000000000000# E: conflict-marker-in-header-entry '#-#-#-#-# la.po (Gizmo Enhancer 1.0) #-#-#-#-#' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "#-#-#-#-# la.po (Gizmo Enhancer 1.0) #-#-#-#-#\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/codomain-error-in-unused-plural-forms.po0000644000000000000000000000134112312562472027736 0ustar00rootroot00000000000000# W: codomain-error-in-unused-plural-forms f(x) != 0, 1, 2, ..., 41 # W: codomain-error-in-unused-plural-forms f(x) != 43, 44, 45, ..., 999999999999999999999 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1000000000000000000000; plural=42\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/codomain-error-in-plural-forms-2.po0000644000000000000000000000152412312562472026577 0ustar00rootroot00000000000000# E: codomain-error-in-plural-forms f(2) = 7 >= 3 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 7 : 2;\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.13.4/tests/blackbox_tests/codomain-error-in-plural-forms-1.po0000644000000000000000000000230212312562472026571 0ustar00rootroot00000000000000# E: incorrect-plural-forms 'nplurals=5; plural=n==1 ? 1 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;' => 'nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;' # E: codomain-error-in-plural-forms f(x) != 0 # E: codomain-error-in-plural-forms f(x) != 3, 4 msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=5; plural=n==1 ? 1 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %d flag." msgstr[3] "Mężny bądź, chroń pułk twój i %d flag." msgstr[4] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.13.4/tests/blackbox_tests/c1-control-characters.po0000644000000000000000000000121712312562472024570 0ustar00rootroot00000000000000# E: unusual-character-in-translation U+0080 control character PAD: 'Sic fugiens, dux, zelotypos, quam Karus haberis\xe2\x80\xa6' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis…" i18nspector-0.13.4/tests/blackbox_tests/c0-control-characters.po0000644000000000000000000000120412312562472024563 0ustar00rootroot00000000000000# E: unusual-character-in-translation U+0019 control character EM: 'Sic fugiens, dux, zelotypos, quam Karus haberis\x19' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis" i18nspector-0.13.4/tests/blackbox_tests/broken-encoding.po0000644000000000000000000000112412312562472023533 0ustar00rootroot00000000000000# E: broken-encoding '<...>\xe2\x80\xa6"\n' cannot be decoded as ASCII msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=US-ASCII\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog..." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis…" i18nspector-0.13.4/tests/blackbox_tests/broken-encoding-due-to-missing-content-type.po0000644000000000000000000000116412312562472031030 0ustar00rootroot00000000000000# E: broken-encoding '<...>\xe2\x80\xa6"\n' cannot be decoded as ASCII # E: no-content-type-header-field Content-Type: text/plain; charset= msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog..." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis…" i18nspector-0.13.4/tests/blackbox_tests/broken-encoding-and-syntax-error.po0000644000000000000000000000120012312562472026741 0ustar00rootroot00000000000000# E: syntax-error-in-po-file line 20 # E: broken-encoding '<...>\xe2\x80\xa6"<...>' cannot be decoded as ASCII msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ASCII\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog..." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis…" msgid i18nspector-0.13.4/tests/blackbox_tests/bom-in-translation.po0000644000000000000000000000113712312562472024210 0ustar00rootroot00000000000000# E: unusual-character-in-translation U+FEFF ZERO WIDTH NO-BREAK SPACE: '\ufeff<...>' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/boilerplate-in-report-msgid-bugs.po0000644000000000000000000000111512312562472026745 0ustar00rootroot00000000000000# W: boilerplate-in-report-msgid-bugs-to 'FULL NAME ' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/boilerplate-in-project-id-version-2.po0000644000000000000000000000107412312562472027261 0ustar00rootroot00000000000000# W: boilerplate-in-project-id-version 'PROJECT VERSION' msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/boilerplate-in-project-id-version-1.po0000644000000000000000000000107412312562472027260 0ustar00rootroot00000000000000# W: boilerplate-in-project-id-version 'PACKAGE VERSION' msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/boilerplate-in-pot-creation-date.po0000644000000000000000000000111212312562472026707 0ustar00rootroot00000000000000# W: boilerplate-in-date POT-Creation-Date: 'YEAR-MO-DA HO:MI+ZONE' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/boilerplate-in-po-revision-date.po0000644000000000000000000000111112312562472026554 0ustar00rootroot00000000000000# W: boilerplate-in-date PO-Revision-Date: 'YEAR-MO-DA HO:MI+ZONE' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/boilerplate-in-last-translator.po0000644000000000000000000000110312312562472026522 0ustar00rootroot00000000000000# W: boilerplate-in-last-translator 'FULL NAME ' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: FULL NAME \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/boilerplate-in-language-team.po0000644000000000000000000000110212312562472026076 0ustar00rootroot00000000000000# W: boilerplate-in-language-team 'LANGUAGE ' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: LANGUAGE \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/boilerplate-in-content-type.po0000644000000000000000000000110712312562472026025 0ustar00rootroot00000000000000# E: boilerplate-in-content-type 'text/plain; charset=CHARSET' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/ancient-pot-creation-date.po0000644000000000000000000000110312312562472025422 0ustar00rootroot00000000000000# W: ancient-date POT-Creation-Date: '1942-04-02 03:37+0100' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 1942-04-02 03:37+0100\n" "PO-Revision-Date: 2012-11-01 14:42+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/ancient-po-revision-date.po0000644000000000000000000000110212312562472025267 0ustar00rootroot00000000000000# W: ancient-date PO-Revision-Date: '1942-04-02 03:37+0100' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net\n" "POT-Creation-Date: 2012-11-01 14:42+0100\n" "PO-Revision-Date: 1942-04-02 03:37+0100\n" "Last-Translator: Jakub Wilk \n" "Language-Team: Latin \n" "Language: la\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.13.4/tests/blackbox_tests/__init__.py0000644000000000000000000002353712312562472022254 0ustar00rootroot00000000000000# Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import difflib import errno import inspect import os import re import shlex import signal import subprocess as ipc import sys import unittest import nose import nose.plugins from .. import aux here = os.path.dirname(__file__) # ---------------------------------------- def this(): ''' Return function that called this fuction. (Hopefully!) ''' return globals()[inspect.stack()[1][0].f_code.co_name] # ---------------------------------------- _parse_etag = re.compile('([A-Z]): (([\w-]+).*)').match def parse_etag(contents, path, multi_line=False): match = _parse_etag(contents) if match is None: return t = ETag(match.group(1), path, match.group(2)) return t def etags_from_tagstring(obj, path): try: docstring = obj.tagstring except AttributeError: return for line in docstring.splitlines(): line = line.lstrip() t = parse_etag(line, path) if t is not None: yield t def tagstring(s): def update(x): x.tagstring = s return x return update # ---------------------------------------- class ETag(object): _ellipsis = '<...>' _split = re.compile('({})'.format(re.escape(_ellipsis))).split def __init__(self, code, path, rest): self._s = s = '{code}: {path}: {rest}'.format( code=code, path=path, rest=rest, ) self.tag = rest.split(None, 1)[0] regexp = ''.join( '.*' if chunk == self._ellipsis else re.escape(chunk) for chunk in self._split(s) ) self._regexp = re.compile('^{}$'.format(regexp)) def __eq__(self, other): if isinstance(other, str): return self._regexp.match(other) else: return NotImplemented def __str__(self): return self._s def __repr__(self): return repr(self._s) # ---------------------------------------- def _get_signal_names(): data = dict( (name, getattr(signal, name)) for name in dir(signal) if re.compile('^SIG[A-Z0-9]*$').match(name) ) try: if data['SIGABRT'] == data['SIGIOT']: del data['SIGIOT'] except KeyError: pass try: if data['SIGCHLD'] == data['SIGCLD']: del data['SIGCLD'] except KeyError: pass for name, n in data.items(): yield n, name _signal_names = dict(_get_signal_names()) def get_signal_name(n): try: return _signal_names[n] except KeyError: return str(n) # ---------------------------------------- test_file_extensions = ('.mo', '.po', '.pot', '.pop') # .pop is a special extension to trigger unknown-file-type class Plugin(nose.plugins.Plugin): name = 'po-plugin' enabled = True def options(self, parser, env): pass def wantFile(self, path): if path.endswith(test_file_extensions): if path.startswith(os.path.join(os.path.abspath(here), '')): return True def loadTestsFromFile(self, path): yield TestCase(path) def wantFunction(self, func): # If the plugin is being used, test_file() is reduntant. # We can't just check whether "func is test_file", because some # versions of nose (at least 1.1.2) reload the module. if func.__name__ == 'test_file' and func.__module__ == test_file.__module__: return False class TestCase(unittest.TestCase): def __init__(self, path): super().__init__('_test') self.path = path def _test(self): _test_file(self.path) def __str__(self): return os.path.relpath(self.path) def assert_emit_tags(path, etags, *, options=()): etags = list(etags) commandline = os.environ.get('I18NSPECTOR_COMMANDLINE') if commandline is None: prog = os.path.join(here, os.pardir, os.pardir, 'i18nspector') commandline = [sys.executable, prog] else: commandline = shlex.split(commandline) commandline += options commandline += [path] fixed_env = dict(os.environ, LC_ALL='C') child = ipc.Popen(commandline, stdout=ipc.PIPE, stderr=ipc.PIPE, env=fixed_env) stdout, stderr = ( s.decode().splitlines() for s in child.communicate() ) rc = child.poll() if rc != 0: if rc < 0: message = ['command was interrupted by signal {sig}'.format(sig=get_signal_name(-rc))] else: message = ['command exited with status {rc}'.format(rc=rc)] message += [''] if stdout: message += ['stdout:'] message += ['| ' + s for s in stdout] + [''] else: message += ['stdout: (empty)'] if stderr: message += ['stderr:'] message += ['| ' + s for s in stderr] else: message += ['stderr: (empty)'] raise AssertionError('\n'.join(message)) expected_failure = os.path.basename(path).startswith('xfail-') if stdout != etags: if expected_failure: raise nose.SkipTest('expected failure') str_etags = [str(x) for x in etags] message = ['Tags differ:', ''] diff = list( difflib.unified_diff(str_etags, stdout, n=9999) ) message += diff[3:] raise AssertionError('\n'.join(message)) elif expected_failure: raise AssertionError('unexpected success') class TestFileSyntaxError(Exception): pass def _parse_test_header_file(file, path, *, comments_only): etags = [] options = [] for n, line in enumerate(file): orig_line = line if comments_only: if n == 0 and line.startswith('#!'): continue if line.startswith('# '): line = line[2:] else: break if line.startswith('--'): options += shlex.split(line) else: etag = parse_etag(line, path) if etag is None: if comments_only: break else: raise TestFileSyntaxError(orig_line) etags += [etag] return etags, options def _parse_test_headers(path): # .tags: try: file = open(path + '.tags', encoding='ASCII') except IOError as exc: if exc.errno != errno.ENOENT: raise else: with file: return _parse_test_header_file(file, path, comments_only=False) # .gen: try: file = open(path + '.gen', encoding='ASCII', errors='ignore') except IOError as exc: if exc.errno != errno.ENOENT: raise else: with file: return _parse_test_header_file(file, path, comments_only=True) # : with open(path, 'rt', encoding='ASCII', errors='ignore') as file: return _parse_test_header_file(file, path, comments_only=True) def _test_file(path): path = os.path.relpath(os.path.join(here, path), start=os.getcwd()) options = [] etags, options = _parse_test_headers(path) assert_emit_tags(path, etags, options=options) def get_coverage_for_file(path): etags, options = _parse_test_headers(path) return (t.tag for t in etags) def get_coverage_for_function(fn): for etag in etags_from_tagstring(fn, ''): yield etag.tag def _get_test_filenames(): for root, dirnames, filenames in os.walk(here): for filename in filenames: if not filename.endswith(test_file_extensions): continue yield os.path.join(root, filename) def test_file(): for filename in _get_test_filenames(): path = os.path.relpath(filename, start=here) yield _test_file, path @tagstring(''' E: os-error No such file or directory ''') def test_os_error_no_such_file(): with aux.temporary_directory() as tmpdir: path = os.path.join(tmpdir, 'nonexistent.po') expected = etags_from_tagstring(this(), path) assert_emit_tags(path, expected) @tagstring(''' E: os-error Permission denied ''') def test_os_error_permission_denied(): if os.getuid() == 0: raise nose.SkipTest('this test must not be run as root') with aux.temporary_directory() as tmpdir: path = os.path.join(tmpdir, 'denied.po') with open(path, 'wb'): pass os.chmod(path, 0) expected = etags_from_tagstring(this(), path) assert_emit_tags(path, expected) # ---------------------------------------- def get_coverage(): coverage = set() for filename in _get_test_filenames(): for tag in get_coverage_for_file(filename): coverage.add(tag) for objname, obj in globals().items(): if not objname.startswith('test_'): continue for tag in get_coverage_for_function(obj): coverage.add(tag) return coverage # vim:ts=4 sw=4 et i18nspector-0.13.4/tests/aux.py0000644000000000000000000000706512312562472016301 0ustar00rootroot00000000000000# Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import contextlib import functools import os import shutil import sys import tempfile import traceback import nose _tmp_prefix = 'i18nspector.tests.' temporary_file = functools.partial( tempfile.NamedTemporaryFile, prefix=_tmp_prefix, ) @contextlib.contextmanager def temporary_directory(): tmpdir = tempfile.mkdtemp(prefix=_tmp_prefix) try: yield tmpdir finally: shutil.rmtree(tmpdir) class IsolatedError(Exception): pass def _n_relevant_tb_levels(tb): n = 0 while tb and '__unittest' not in tb.tb_frame.f_globals: n += 1 tb = tb.tb_next return n def fork_isolation(f): EXIT_EXCEPTION = 101 EXIT_SKIP_TEST = 102 exit = os._exit # sys.exit() can't be used here, because nose catches all exceptions, # including SystemExit @functools.wraps(f) def wrapper(*args, **kwargs): readfd, writefd = os.pipe() pid = os.fork() if pid == 0: os.close(readfd) try: f(*args, **kwargs) except nose.SkipTest as exc: s = str(exc).encode('UTF-8') with os.fdopen(writefd, 'wb') as fp: fp.write(s) exit(EXIT_SKIP_TEST) except Exception: exctp, exc, tb = sys.exc_info() s = traceback.format_exception(exctp, exc, tb, _n_relevant_tb_levels(tb)) s = ''.join(s).encode('UTF-8') del tb with os.fdopen(writefd, 'wb') as fp: fp.write(s) exit(EXIT_EXCEPTION) exit(0) else: os.close(writefd) with os.fdopen(readfd, 'rb') as fp: msg = fp.read() msg = msg.decode('UTF-8').rstrip('\n') pid, status = os.waitpid(pid, 0) if status == (EXIT_EXCEPTION << 8): raise IsolatedError('\n\n' + msg) elif status == (EXIT_SKIP_TEST << 8): raise nose.SkipTest(msg) elif status == 0 and msg == '': pass else: raise RuntimeError('unexpected isolated process status {}'.format(status)) return wrapper basedir = os.path.join( os.path.dirname(__file__), os.pardir, ) basedir = os.environ.get('I18NSPECTOR_BASEDIR', basedir) basedir = os.path.join(basedir, '') os.stat(basedir) datadir = os.path.join(basedir, 'data') os.stat(datadir) sys.path[:0] = [basedir] # vim:ts=4 sw=4 et i18nspector-0.13.4/tests/__init__.py0000644000000000000000000000015712312562472017236 0ustar00rootroot00000000000000import sys if sys.version_info < (3, 0): raise ImportError('Python >= 3 is required') # vim:ts=4 sw=4 et i18nspector-0.13.4/private/0000755000000000000000000000000012312562472015432 5ustar00rootroot00000000000000i18nspector-0.13.4/private/update-version0000755000000000000000000000034412312562472020326 0ustar00rootroot00000000000000#!/bin/sh version=${1:?"no version number provided"} set -e -x dch -m -v "$version" -c doc/changelog sed -i -r -e "s/(__version__) = '\S+'/\1 = '$version'/" lib/*.py sed -i -r -e "s/^(:version: \S+) \S+$/\1 $version/" doc/*.txt i18nspector-0.13.4/private/update-timezones0000755000000000000000000000517412312562472020664 0ustar00rootroot00000000000000#!/usr/bin/python3 # Copyright © 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import collections import datetime import os import sys import pytz basedir = '{here}/..'.format(here=os.path.dirname(__file__)) sys.path[:0] = [basedir] import lib.gettext as gettext def main(): minyear = gettext.epoch.year maxyear = datetime.date.today().year + 1 tzdata = collections.defaultdict(set) for tzname in pytz.all_timezones: if tzname.startswith('Etc/'): continue tz = pytz.timezone(tzname) try: timestamps = list(tz._utc_transition_times) except AttributeError: timestamps = [] timestamps += [datetime.datetime(minyear, 1, 1)] for timestamp in timestamps: if not (minyear <= timestamp.year <= maxyear): continue timestamp = tz.fromutc(timestamp) code, offset = timestamp.strftime('%Z %z').split() assert 3 <= len(code) <= 6 tzdata[code].add(offset) path = os.path.join(basedir, 'data', 'timezones') sys.stdout = open(path + '.tmp', 'wt', encoding='ASCII') print('''\ # This file has been generated automatically by private/update-timezones. # Do not edit. # Last update: {today} '''.format(today=datetime.date.today())) print('[timezones]') for code, offsets in sorted(tzdata.items()): print('{code} = {offsets}'.format(code=code, offsets=' '.join(sorted(offsets)))) print() print('# vi''m:ft=dosini') sys.stdout.close() os.rename(path + '.tmp', path) if __name__ == '__main__': main() # vim:ts=4 sw=4 et i18nspector-0.13.4/private/update-tags0000755000000000000000000000430412312562472017577 0ustar00rootroot00000000000000#!/usr/bin/python3 # Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import ast import os import sys basedir = os.path.join( os.path.dirname(__file__), os.pardir, ) sys.path[:0] = [basedir] from lib import tags def extract_tagnames(node): for child in ast.iter_child_nodes(node): for t in extract_tagnames(child): yield t if ( isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute) and node.func.attr == 'tag' and node.args and isinstance(node.args[0], ast.Str) ): yield node.args[0].s def main(): source_path = os.path.join(basedir, 'lib', 'checker.py') with open(source_path, 'rt', encoding='UTF-8') as file: source = file.read() node = ast.parse(source, filename=source_path) tagnames = set(extract_tagnames(node)) del source, node for tagname in sorted(tagnames): if tags.tag_exists(tagname): continue print('[{tag}]'.format(tag=tagname)) print('severity = wishlist') print('certainty = wild-guess') print() if __name__ == '__main__': main() # vim:ts=4 sw=4 et i18nspector-0.13.4/private/update-tag-coverage0000755000000000000000000000410312312562472021202 0ustar00rootroot00000000000000#!/usr/bin/python3 # Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import os import sys basedir = os.path.join( os.path.dirname(__file__), os.pardir, ) sys.path[:0] = [basedir] from lib import tags from tests import blackbox_tests def main(): coverage = blackbox_tests.get_coverage() path = os.path.join( os.path.dirname(blackbox_tests.__file__), 'coverage.txt' ) sys.stdout = open(path + '.tmp', 'wt', encoding='ASCII') print('Generated automatically by private/update-tag-coverage. ' 'Do not edit.\n') for tag in tags.iter_tags(): check = 'X' if tag.name in coverage else ' ' print('[{check}] {tag}'.format(check=check, tag=tag.name)) sys.stdout.close() os.rename(path + '.tmp', path) rc = 0 for tag in sorted(set(coverage) - set(t.name for t in tags.iter_tags())): print('update-coverage: error: uknown tag {tag}'.format(tag=tag), file=sys.stderr) rc = 1 sys.exit(rc) if __name__ == '__main__': main() # vim:ts=4 sw=4 et i18nspector-0.13.4/private/update-poedit-data0000755000000000000000000000534512312562472021042 0ustar00rootroot00000000000000#!/usr/bin/python3 # Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import os import re import sys import urllib.request basedir = os.path.join( os.path.dirname(__file__), os.pardir, ) sys.path[:0] = [basedir] from lib import ling def main(): url = 'https://raw.github.com/vslavik/poedit/master/src/isocodes.cpp' regexp = re.compile(r'^\s*\{\s*_T\("([a-z]{2,}(?:_[A-Z]{2})?(?:@[a-z]+)?)"\)\s*,\s*_T\("([^"]+)"\)\s*\}\s*,?\s*$') n_okay = 0 with urllib.request.urlopen(url) as file: for line in file: line = line.decode('ASCII').rstrip() match = regexp.match(line) if match is None: continue poedit_ll, name = match.groups() poedit_ll = ling.parse_language(poedit_ll) try: gi_ll = ling.get_language_for_name(name) except LookupError: gi_ll = None if gi_ll != poedit_ll: print('[{}]'.format(poedit_ll)) try: if poedit_ll.fix_codes(): raise ling.LanguageError except ling.LanguageError: if gi_ll is None: print('# Unknown language code') else: print('# Unknown language code; should be: {}'.format(gi_ll)) else: if gi_ll is not None: print('# Not {}'.format(gi_ll)) print('names =', name) print() else: n_okay += 1 print('# No changes required for {} languages'.format(n_okay)) if __name__ == '__main__': main() # vim:ts=4 sw=4 et i18nspector-0.13.4/private/update-line-coverage0000755000000000000000000000437612312562472021372 0ustar00rootroot00000000000000#!/usr/bin/python3 # Copyright © 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import glob import io import os import sys import nose import nose.plugins.cover class Coverage(nose.plugins.cover.Coverage): stream = None def report(self, stream): return super().report(self.stream) basedir = os.path.join( os.path.dirname(__file__), os.pardir, ) def main(): module_glob = os.path.join(basedir, 'tests', 'test_*.py') modules = glob.glob(module_glob) argv = [ sys.argv[0], '--with-coverage', '--cover-package=lib', '--cover-erase', ] + modules path = os.path.join( 'tests', 'coverage.txt' ) plugin = Coverage() report_stream = plugin.stream = io.StringIO() print('Generated automatically by private/update-line-coverage. ' 'Do not edit.\n', file=report_stream) ok = nose.run(argv=argv, plugins=[plugin]) if not ok: sys.exit(1) report_stream.seek(0) with open(path + '.tmp', 'wt', encoding='ASCII') as file: for line in report_stream: line = line.rstrip() print(line, file=file) os.rename(path + '.tmp', path) if __name__ == '__main__': main() # vim:ts=4 sw=4 et i18nspector-0.13.4/private/update-iso-codes0000755000000000000000000001313512312562472020530 0ustar00rootroot00000000000000#!/usr/bin/python3 # Copyright © 2012, 2013, 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import datetime import functools import os import subprocess as ipc import sys import xml.etree.cElementTree as etree class Panic(ValueError): pass @functools.lru_cache() def get_iso_codes_version(): version = ipc.check_output(['pkg-config', 'iso-codes', '--modversion']) version = version.decode('ASCII').strip() return version @functools.lru_cache() def get_iso_codes_dir(): prefix = ipc.check_output(['pkg-config', 'iso-codes', '--variable=prefix']) prefix = prefix.decode('ASCII').strip() return '{prefix}/share/xml/iso-codes/'.format(prefix=prefix) def main(): basedir = os.path.join( os.path.dirname(__file__), os.pardir, ) path = os.path.join(basedir, 'data', 'iso-codes') sys.stdout = open(path + '.tmp', 'wt', encoding='UTF-8') print('''\ # This file has been generated automatically by private/update-iso-codes. # Do not edit. # iso-codes version: {version} # Last update: {today} '''.format(version=get_iso_codes_version(), today=datetime.date.today())) generate_iso_639() generate_iso_3166() sys.stdout.close() os.rename(path + '.tmp', path) def generate_iso_639(): # ======================= # ISO 639: language codes # ======================= l2t_to_2b = {} iso_639 = {} for event, element in etree.iterparse(os.path.join(get_iso_codes_dir(), 'iso_639.xml')): if element.tag != 'iso_639_entry': continue l2b = element.get('iso_639_2B_code') l2t = element.get('iso_639_2T_code') if l2b == l2t == 'qaa-qtz': continue for l in l2b, l2t: if len(l) != 3: raise Panic('len({!r}) != 3'.format(l)) if l2b != l2t: l2t_to_2b[l2t] = l2b iso_639 = {} for event, element in etree.iterparse(os.path.join(get_iso_codes_dir(), 'iso_639_3.xml')): if element.tag != 'iso_639_3_entry': continue code = element.get('id') if len(code) != 3: raise Panic('len({!r}) != 3'.format(code)) code1 = element.get('part1_code') code2 = element.get('part2_code') if code2 is None: # We're not interested in languages that are not in 639-2 (yet?). continue if code2 != code: raise Panic('{!r} != {!r}'.format(code, code2)) scope = element.get('scope') if scope in {'S', 'L'}: # Not a real language, ignore. continue elif scope == 'C': # We're not interested in collective languages (yet?). if code1 is None: continue elif scope in {'M', 'I'}: pass else: raise Panic('unknown scope: {!r}'.format(scope)) status = element.get('status') if status == 'Active': pass elif status == 'Retired': continue else: raise Panic('unknown status: {!r}'.format(status)) reference_name = element.get('reference_name') if reference_name in iso_639: raise Panic('duplicate reference name: {!r}'.format(reference_name)) if code1 is not None: if code1.endswith('(deprecated)'): code1 = None if code1 is not None: if len(code1) == 2: codelist = [code1, code] else: raise Panic('len({!r}) != 2'.format(code1)) else: codelist = [code] try: codelist += [l2t_to_2b[code]] except KeyError: pass iso_639[reference_name] = codelist print('[language-codes]') iso_639_rev = {} for code, *aliases in iso_639.values(): for alias in aliases: iso_639_rev[alias] = code if not aliases: iso_639_rev[code] = '' for alias, code in sorted(iso_639_rev.items()): print('{} = {}'.format(alias, code).rstrip()) print() def generate_iso_3166(): # ========================= # ISO 3166: territory codes # ========================= iso_3166 = set() for event, element in etree.iterparse(os.path.join(get_iso_codes_dir(), 'iso_3166.xml')): if element.tag != 'iso_3166_entry': continue cc = element.get('alpha_2_code') if cc is None: raise ValueError iso_3166.add(cc) print('[territory-codes]') for cc in sorted(iso_3166): print('{} ='.format(cc)) print() print('# vi''m:ft=dosini') if __name__ == '__main__': main() # vim:ts=4 sw=4 et i18nspector-0.13.4/private/update-header-fields0000755000000000000000000000525212312562472021340 0ustar00rootroot00000000000000#!/usr/bin/python3 # Copyright © 2012, 2013, 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import os import shutil import subprocess as ipc import tempfile xgettexts = {'xgettext', 'pygettext'} def main(): os.environ['LC_ALL'] = 'C' tmpdir = tempfile.mkdtemp(prefix='i18nspector.private.') xgettext_versions = { ipc.check_output([xgettext, '--version']).splitlines()[0].decode('ASCII', 'replace') for xgettext in xgettexts } try: path = os.path.join(tmpdir, 'dummy.c') with open(path, 'wt', encoding='ASCII') as file: file.write('ngettext("1", "2");') pos = { ipc.check_output([xgettext, '-o', '-', path]) for xgettext in xgettexts } finally: shutil.rmtree(tmpdir) headers = set() for po in pos: po = po.decode('ASCII').splitlines() for line in po: if line.startswith('"'): header = line[1:].split(':', 1)[0] headers.add(header) basedir = os.path.join( os.path.dirname(__file__), os.pardir, ) path = os.path.join(basedir, 'data', 'header-fields') with open(path, 'wt', encoding='ASCII') as file: print('''\ # This file has been generated automatically by # private/update-header-fields. Do not edit. # # The following string extraction tools have been used:\ ''', file=file) for xgettext_version in sorted(xgettext_versions): print('# *', xgettext_version, file=file) print(file=file) for header in sorted(headers): print(header, file=file) if __name__ == '__main__': main() # vim:ts=4 sw=4 et i18nspector-0.13.4/private/update-gettext-data0000755000000000000000000001326712312562472021244 0ustar00rootroot00000000000000#!/usr/bin/python3 # Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import datetime import os import re import sys import urllib.request basedir = os.path.join( os.path.dirname(__file__), os.pardir, ) sys.path[:0] = [basedir] from lib import ling def strip_plural_forms(s): # Remove superfluous parentheses around the plural formula: return re.sub(r'\bplural=\((.*?)\);$', r'plural=\1;', s) def do_plurals(): regexp = re.compile(r'\s+{\s*"([a-zA-Z_]+)".*"(nplurals.*?)"') url = 'http://git.savannah.gnu.org/cgit/gettext.git/plain/gettext-tools/src/plural-table.c' okay = set() with urllib.request.urlopen(url) as file: for line in file: line = line.decode('ASCII').rstrip() match = regexp.match(line) if match is None: continue language, gettext_plural_forms = match.groups() language = ling.parse_language(language) gettext_plural_forms = strip_plural_forms(gettext_plural_forms) our_plural_forms = language.get_plural_forms() if our_plural_forms != [gettext_plural_forms]: print('[{}]'.format(language)) if our_plural_forms != None: if len(our_plural_forms) == 1: print('# plural-forms =', our_plural_forms) else: print('# plural-forms =') for pf in our_plural_forms: print('# ', pf) print('plural-forms =', gettext_plural_forms) print() else: okay.add(str(language)) n_okay = len(okay) print('# No plural-forms changes required for {} languages'.format(n_okay)) print() def do_languages(): url = 'http://git.savannah.gnu.org/cgit/gettext.git/plain/gettext-tools/src/msginit.c' okay = set() with urllib.request.urlopen(url) as file: contents = file.read() match = re.compile(br'locales_with_principal_territory\s*\[\]\s*=\s*[{](.*?)[}]', re.DOTALL).search(contents) if match is None: raise ValueError contents = match.group(1) contents = re.compile(br'/[*].*?[*]/', re.DOTALL).sub(b'', contents) contents = contents.decode('ASCII') data = {} primary_languages = set(ling.get_primary_languages()) for item in re.findall('"(\w+)"', contents): language, gettext_cc = item.split('_') if language not in primary_languages: continue data[language] = gettext_cc our_cc = ling.parse_language(language).get_principal_territory_code() if our_cc != gettext_cc: print('[{}]'.format(language)) if our_cc is not None: print('# WAS: principal-territory =', our_cc) if ling.lookup_territory_code(gettext_cc) is None: print('# BAD: principal-territory =', gettext_cc) else: print('principal-territory =', gettext_cc) print() else: okay.add(language) for language in sorted(primary_languages): if '_' in language: continue cc = ling.parse_language(language).get_principal_territory_code() if cc is None: continue if language not in data: print('# WAS: [{}]'.format(language)) print('# WAS: principal-territory =', cc) print() n_okay = len(okay) print('# No principal-territory changes required for {} languages'.format(n_okay)) print() template = '''\ # This file has been generated automatically by private/update-gettext-data. # Do not edit. # Last update: {today} ''' def do_string_formats(): url = 'http://git.savannah.gnu.org/cgit/gettext.git/plain/gettext-tools/src/message.c' with urllib.request.urlopen(url) as file: contents = file.read() match = re.compile(br'\sformat_language\s*\[NFORMATS\]\s*=\s*[{](.*?)[}]', re.DOTALL).search(contents) if match is None: raise ValueError contents = match.group(1) contents = re.compile(br'/[*].*?[*]/', re.DOTALL).sub(b'', contents) contents = contents.decode('ASCII') formats = re.findall('"([\w-]+)"', contents) path = os.path.join(basedir, 'data', 'string-formats') with open(path + '.tmp', 'wt', encoding='ASCII') as stdout: print(template.format(today=datetime.date.today()), file=stdout) for item in sorted(formats): print(item, file=stdout) os.rename(path + '.tmp', path) print('# Saved {} string formats'.format(len(formats))) def main(): do_plurals() do_languages() do_string_formats() if __name__ == '__main__': main() # vim:ts=4 sw=4 et i18nspector-0.13.4/private/update-charmaps0000755000000000000000000000436612312562472020447 0ustar00rootroot00000000000000#!/usr/bin/python3 # Copyright © 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import os import sys basedir = os.path.join( os.path.dirname(__file__), os.pardir, ) sys.path[:0] = [basedir] from lib import encodings from lib import iconv def generate_charmap(encoding): encoding = encoding.upper() print(encoding, '...', end=' ') sys.stdout.flush() path = '{base}/data/charmaps/{enc}'.format(base=basedir, enc=encoding) n = 0 us = [] for b in range(0x100): b = bytes([b]) try: u = iconv.decode(b, encoding) except UnicodeDecodeError: u = '\uFFFE' else: n += 1 assert len(u) == 1 us += [u] if n <= 128: print('SKIP (not 8-bit)') return assert len(us) == 0x100 with open(path, 'wb') as file: us = ''.join(us) assert len(us) == 0x100 file.write(us.encode('UTF-8')) print('ok') def main(): for encoding, codec in encodings._portable_encodings.items(): if codec is None: generate_charmap(encoding) for encoding in encodings._extra_encodings: generate_charmap(encoding) if __name__ == '__main__': main() # vim:ts=4 sw=4 et i18nspector-0.13.4/private/update-blackbox-tests0000755000000000000000000000324312312562472021567 0ustar00rootroot00000000000000#!/usr/bin/python3 # Copyright © 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import os import subprocess as ipc def main(): test_dir = '{here}/../tests/blackbox_tests/'.format( here=os.path.dirname(__file__), ) os.chdir(test_dir) for generator in os.listdir('.'): if not generator.endswith('.gen'): continue target = generator[:-4] tmp_target = target + '.tmp' env = dict(os.environ, here='.', target=tmp_target) ipc.check_call(os.path.join('.', generator), env=env) os.rename(tmp_target, target) if __name__ == '__main__': main() # vim:ts=4 sw=4 et i18nspector-0.13.4/private/tags-as-rst0000755000000000000000000000400512312562472017524 0ustar00rootroot00000000000000#!/usr/bin/python3 # Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import io import os import sys basedir = os.path.join( os.path.dirname(__file__), os.pardir, ) sys.path[:0] = [basedir] from lib import tags def output_tags_rst(tags): print('''\ .. This file has been generated automatically by private/tags-as-rst. Do not edit. ''') for tag in tags: tagname = tag.name print(tagname) print('~' * len(tagname)) print(tag.description) print() if tag.references: print('References:', end='\n\n') for ref in tag.references: print(' ', ref) print() print('Severity, certainty:', end='\n\n') print(' {}, {}'.format(tag.severity, tag.certainty)) print() def main(): sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='UTF-8') output_tags_rst(tags.iter_tags()) if __name__ == '__main__': main() # vim:ts=4 sw=4 et i18nspector-0.13.4/private/collect-metadata0000755000000000000000000001130712312562472020565 0ustar00rootroot00000000000000#!/usr/bin/python3 # Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import argparse import collections import itertools import os import re import sys import polib def init_polib(): # Happily decode any file, even when encoding declaration is broken or # missing. polib.default_encoding = 'ISO-8859-1' is_sane_field_name = re.compile('^[a-zA-Z-]+$').match _extract_address = re.compile(r'''^(?: .*< ( [^<>]+@[^<>]+ ) >\s* | ( \S+@\S+ ) | .*< ( https?://[^<>]+ ) >\s* | .*[(] ( https?://[^()]+ ) [)]\s* | \s* (https?://\S+) \s* )$''', re.VERBOSE).match def extract_address(s): match = _extract_address(s) if match is None: return [result] = filter(None, match.groups()) return result def main(): init_polib() ap = argparse.ArgumentParser() ap.add_argument('files', metavar='', nargs='*') ap.add_argument('-F', '--field', help='only this field') ap.add_argument('--insane', action='store_true', help='allow insane field names') ap.add_argument('--extract-addresses', action='store_true') ap.add_argument('--all-test-cases', action='store_true') ap.add_argument('--plural-only', action='store_true', help='consider only translations with plural forms') ap.add_argument('--stdin', action='store_true', help='read filenames from stdin') options = ap.parse_args() metadata = collections.defaultdict(collections.Counter) if options.all_test_cases: test_cases = collections.defaultdict(set) else: test_cases = {} files = options.files if options.stdin: files = itertools.chain( files, (l.rstrip() for l in sys.stdin) ) for path in files: print(path, end=' ... ', file=sys.stderr) sys.stderr.flush() try: extension = os.path.splitext(path)[-1] if extension == '.po': constructor = polib.pofile elif extension in ('.mo', '.gmo'): constructor = polib.mofile else: raise NotImplementedError(repr(extension)) file = constructor(path) if options.plural_only: for msg in file.translated_entries(): if msg.msgstr_plural: break else: print('skip', file=sys.stderr) sys.stderr.flush() continue for k, v in file.metadata.items(): if (not is_sane_field_name(k)) and (not options.insane): continue if not (options.field is None or k == options.field): continue if options.extract_addresses: v = extract_address(v) metadata[k][v] += 1 if options.all_test_cases: test_cases[k, v].add(path) else: test_cases[k, v] = path file = None except Exception as exc: print('error:', exc, file=sys.stderr) else: print('ok', file=sys.stderr) sys.stderr.flush() for key, values in sorted(metadata.items()): print('{key!r}:'.format(key=key)) for value, n in values.most_common(): if options.all_test_cases: print(' {n:6} {value!r}'.format(n=n, value=value)) for path in sorted(test_cases[key, value]): print(' + {path!r}'.format(path=path)) else: path = test_cases[key, value] print(' {n:6} {value!r}; test-case: {path!r}'.format(n=n, value=value, path=path)) if __name__ == '__main__': main() # vim:ts=4 sw=4 et i18nspector-0.13.4/private/collect-characters0000755000000000000000000000614412312562472021127 0ustar00rootroot00000000000000#!/usr/bin/python3 # Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import argparse import collections import itertools import os import sys import polib def init_polib(): # don't assume UTF-8 encoding polib.default_encoding = 'ASCII' def main(): init_polib() ap = argparse.ArgumentParser() ap.add_argument('files', metavar='', nargs='*') ap.add_argument('--skip-ascii', action='store_true', help='skip ASCII characters') ap.add_argument('--stdin', action='store_true', help='read filenames from stdin') options = ap.parse_args() files = options.files if options.stdin: files = itertools.chain( files, (l.rstrip() for l in sys.stdin) ) char_counter = collections.Counter() char_files = collections.defaultdict(set) n_files = 0 for path in files: print(path, end=' ... ', file=sys.stderr) sys.stderr.flush() try: extension = os.path.splitext(path)[-1] if extension == '.po': constructor = polib.pofile elif extension in ('.mo', '.gmo'): constructor = polib.mofile else: raise NotImplementedError(repr(extension)) file = constructor(path) for message in file.translated_entries(): for text in itertools.chain([message.msgstr], message.msgstr_plural.values()): for ch in text: char_counter[ch] += 1 char_files[ch].add(path) file = None except Exception as exc: print('error:', exc, file=sys.stderr) else: print('ok', file=sys.stderr) sys.stderr.flush() n_files += 1 for n, ch in sorted(((n, ch) for ch, n in char_counter.items()), reverse=True): if options.skip_ascii and ord(ch) < 0x80: continue filecov = len(char_files[ch]) / n_files print('{n:6} [{fc:6.1%}] {ch!r}'.format(n=n, fc=filecov, ch=ch)) if __name__ == '__main__': main() # vim:ts=4 sw=4 et i18nspector-0.13.4/private/build-source-tarball0000755000000000000000000000124512312562472021376 0ustar00rootroot00000000000000#!/bin/sh name=i18nspector url=http://bitbucket.org/jwilk/i18nspector if [ $# -ne 1 ] then printf "%s \n" "$0" >&2 exit 1 fi set -e -x pwd="$PWD" version="$1" sourceroot=$(mktemp -d -t "$name-source-XXXXXX") export TAR_OPTIONS="--owner root --group root --mode a+rX --format ustar" export GZIP="-9 -n" mkdir -p "$sourceroot/$name-$version" if [ -d .hg ] then hg archive -r "$version" "$sourceroot/$name-$version" else hg clone -r "$version" "$url" "$sourceroot/$name-$version" fi cd "$sourceroot"/* make -C doc/ find -name '__pycache__' | xargs rm -rf rm -rf .hg* cd .. tar -czf "$pwd/$name-$version.tar.gz" */ rm -rf "$sourceroot" # vim:ts=4 sw=4 et i18nspector-0.13.4/private/add-languages0000755000000000000000000000476212312562472020065 0ustar00rootroot00000000000000#!/usr/bin/python3 # Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import argparse import os import xml.etree.cElementTree as etree iso_codes_dir = '/usr/share/xml/iso-codes/'; def main(): ap = argparse.ArgumentParser() ap.add_argument('languages', metavar='', nargs='+') options = ap.parse_args() languages = set(options.languages) for event, element in etree.iterparse(os.path.join(iso_codes_dir, 'iso_639.xml')): if element.tag != 'iso_639_entry': continue ll = element.get('iso_639_1_code') lll_b = element.get('iso_639_2B_code') lll_t = element.get('iso_639_2T_code') requested = None for lang in ll, lll_b, lll_t: if lang in languages: assert lang is not None requested = lang languages.remove(lang) if requested is None: continue lang = ll or lll_t if lang is None: raise ValueError names = [ s.strip() for s in element.get('name').split(';') ] print('[{}]'.format(requested)) if lang != requested: print('# XXX mapping {} => {}'.format(requested, lang)) if len(names) == 1: print('names =', *names) else: print('names =') for name in names: print('', name) print() if __name__ == '__main__': main() # vim:ts=4 sw=4 et i18nspector-0.13.4/lib/0000755000000000000000000000000012312562473014527 5ustar00rootroot00000000000000i18nspector-0.13.4/lib/terminal.py0000644000000000000000000000516312312562472016720 0ustar00rootroot00000000000000# Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' color terminal support ''' import functools import re class _dummy_curses: def tigetstr(*args, **kwargs): return b'' def tparm(*args, **kwargs): return b'' _curses = _dummy_curses class colors: black = NotImplemented red = NotImplemented green = NotImplemented yellow = NotImplemented blue = NotImplemented magenta = NotImplemented cyan = NotImplemented white = NotImplemented _strip_delay = functools.partial( re.compile(b'[$]<([0-9]*[.])?[0-9]+([/*]|[*][/])?>').sub, b'' ) def attr_fg(i): ''' returns a string that changes the foreground color ''' s = _curses.tigetstr('setaf') or b'' s = _strip_delay(s) s = _curses.tparm(s, i) return s.decode() def attr_reset(): ''' returns a string that resets all attributes ''' s = _curses.tigetstr('sgr0') or b'' s = _strip_delay(s) return s.decode() def initialize(): ''' initialize the terminal ''' global _curses try: import curses as _curses except ImportError: return try: _curses.setupterm() except _curses.error: _curses = _dummy_curses return try: _curses.tparm(b'x') except TypeError: # http://bugs.python.org/issue10570 _curses = _dummy_curses return for key, value in vars(_curses).items(): if key.startswith('COLOR_'): key = key[6:].lower() getattr(colors, key) setattr(colors, key, value) # vim:ts=4 sw=4 et i18nspector-0.13.4/lib/tags.py0000644000000000000000000001455412312562472016047 0ustar00rootroot00000000000000# Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' tag support ''' import configparser import functools import os import re from . import misc from . import paths from . import terminal @functools.total_ordering class OrderedObject(object): _parent = None def __init__(self, name, value): assert self._parent is not None self._name = name self._value = value def __lt__(self, other): if not isinstance(other, OrderedObject): return NotImplemented if self._parent is not other._parent: return NotImplemented return self._value < other._value def __eq__(self, other): if not isinstance(other, OrderedObject): return NotImplemented if self._parent is not other._parent: return NotImplemented return self._value == other._value def __hash__(self): return hash(self._value) def __str__(self): return str(self._name) class OrderedGroup(object): def __init__(self, name, *items): self._child_type = ct = type(name, (OrderedObject,), dict(_parent=self)) self._objects = dict( (name, ct(name, value)) for value, name in enumerate(items) ) def __getitem__(self, name): return self._objects[name] severities = OrderedGroup('Severity', 'pedantic', 'wishlist', 'minor', 'normal', 'important', 'serious' ) certainties = OrderedGroup('Certainty', 'wild-guess', 'possible', 'certain', ) class InvalidSeverity(misc.DataIntegrityError): pass class InvalidCertainty(misc.DataIntegrityError): pass class UnknownField(misc.DataIntegrityError): pass _is_safe = re.compile(r'\A[A-Za-z0-9_.!<>=-]+\Z').match class safestr(str): pass def _escape(s): if isinstance(s, safestr): return s if isinstance(s, bytes): return repr(s)[1:] s = str(s) if s == '': return '(empty string)' elif _is_safe(s): return s else: return repr(s) def safe_format(template, *args, **kwargs): args = [_escape(s) for s in args] kwargs = {k: _escape(v) for k, v in kwargs.items()} return safestr(template.format(*args, **kwargs)) class Tag(object): def __init__(self, **kwargs): self.description = None self.references = [] for k, v in kwargs.items(): try: getattr(self, '_set_' + k)(v) except AttributeError: raise UnknownField(k) self.name, self.severity, self.certainty def _set_name(self, value): self.name = value def _set_severity(self, value): try: self.severity = severities[value] except KeyError as exc: [key] = exc.args raise InvalidSeverity(key) def _set_certainty(self, value): try: self.certainty = certainties[value] except KeyError as exc: [key] = exc.args raise InvalidCertainty(key) _strip_leading_dot = functools.partial( re.compile('^[.]', re.MULTILINE).sub, '' ) @classmethod def _parse_multiline(cls, value): for s in value.splitlines(): if not s or s.isspace(): continue yield cls._strip_leading_dot(s) def _set_description(self, value): value = '\n'.join(self._parse_multiline(value)) self.description = value def _set_references(self, value): self.references += self._parse_multiline(value) def get_colors(self): prio = self.get_priority() n = dict( P=terminal.colors.green, I=terminal.colors.cyan, W=terminal.colors.yellow, E=terminal.colors.red, )[prio] return ( terminal.attr_fg(n), terminal.attr_reset() ) def get_priority(self): s = self.severity S = severities c = self.certainty C = certainties return { S['pedantic']: 'P', S['wishlist']: 'I', S['minor']: 'IW'[c >= C['certain']], S['normal']: 'IW'[c >= C['possible']], S['important']: 'WE'[c >= C['possible']], S['serious']: 'E', }[s] def format(self, target, *extra, color=False): if color: color_on, color_off = self.get_colors() else: color_on = color_off = '' s = '{prio}: {target}: {on}{tag}{off}'.format( prio=self.get_priority(), target=target, tag=self.name, on=color_on, off=color_off, ) if extra: s += ' ' + ' '.join(map(_escape, extra)) return s def _read_tags(): path = os.path.join(paths.datadir, 'tags') cp = configparser.ConfigParser(interpolation=None, default_section='') cp.read(path, encoding='UTF-8') misc.check_sorted(cp) tags = {} for tagname, section in cp.items(): if not tagname: continue kwargs = dict(section.items()) kwargs['name'] = tagname tags[tagname] = Tag(**kwargs) return tags _tags = _read_tags() def tag_exists(tagname): return tagname in _tags def iter_tags(): return (tag for _, tag in sorted(_tags.items())) def get_tag(tagname): return _tags[tagname] # vim:ts=4 sw=4 et i18nspector-0.13.4/lib/polib4us.py0000644000000000000000000001217412312562472016646 0ustar00rootroot00000000000000# Copyright © 2012, 2013, 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' polib monkey-patching ''' import ast import codecs import contextlib import inspect import re import polib from . import encodings from . import moparser patches = [] def install_patches(patches=patches): for patch in patches: patch() __all__ = ['install_patches'] def register_patch(patch): patches.append(contextlib.contextmanager(patch)) # polib.default_encoding # ====================== # Do not allow broken/missing encoding declarations, unless the file is # ASCII-only. @register_patch def default_encoding_patch(): polib.default_encoding = 'ASCII' # polib.codecs # ============ # Work around a few PO parsing bugs: # - newline decoding: http://bugs.debian.org/692283 # - trailing comment parsing: https://bitbucket.org/izi/polib/issue/51 # - atypical comment parsing # - parsing of empty files: https://bitbucket.org/izi/polib/issue/59 class Codecs(object): _iterlines = re.compile(r'[^\n]*(?:\n|\Z)').findall _atypical_comment = re.compile(r'#[^ .:,|~]').match def __getattr__(self, attr): return getattr(codecs, attr) def open(self, path, mode, encoding): if mode not in {'rU', 'rt'}: raise NotImplementedError if not encodings.is_ascii_compatible_encoding(encoding): encoding = 'ASCII' with open(path, 'rb') as file: contents = file.read() contents = contents.decode(encoding) pending_comments = [] empty = True for line in self._iterlines(contents): if self._atypical_comment(line): line = '# ' + line[1:] if line[:2] in {'', '# '} or line.isspace(): pending_comments += [line] else: for comment_line in pending_comments: yield comment_line pending_comments = [] yield line empty = False if empty: yield '# ' @register_patch def codecs_patch(): polib.codecs = polib.io = Codecs() # polib.POFile.find() # =================== # Make POFile.find() always return None. # That way the parser won't find the header entry, allowing us to parse it # ourselves. @register_patch def pofile_find_patch(): def pofile_find(self, *args, **kwargs): return polib.POFile.find = pofile_find # polib.unescape() # ================ # Work around an escape sequence decoding bug # . _escapes_re = re.compile(r''' ( \\ (?: [ntbrfva] | \\ | " | [0-9]{1,3} | x[0-9a-fA-F]{1,2} ))+ ''', re.VERBOSE) _short_x_escape_re = re.compile(r''' \\x ([0-9a-fA-F]) (?= \\ | $ ) ''', re.VERBOSE) def polib_unescape(s): def unescape(match): s = match.group() s = _short_x_escape_re.sub(r'\x0\1', s) result = ast.literal_eval("b'{}'".format(s)) try: return result.decode('ASCII') except UnicodeDecodeError: # an ugly hack to discover encoding of the PO file: parser_stack_frame = inspect.stack()[2][0] parser = parser_stack_frame.f_locals['self'] encoding = parser.instance.encoding return result.decode(encoding) return _escapes_re.sub(unescape, s) @register_patch def unescape_patch(): polib.unescape = polib_unescape # polib._MOFileParser # =================== # Use a custom MO file parser implementation. # https://bitbucket.org/izi/polib/issue/36 # https://bitbucket.org/izi/polib/issue/44 # https://bitbucket.org/izi/polib/issue/45 # https://bitbucket.org/izi/polib/issue/47 @register_patch def mo_parser_patch(): polib._MOFileParser = moparser.Parser # polib.detect_encoding() # ======================= # Don't use polib's detect_encoding() for MO files, as i18nspector's own MO # file parser has built-in encoding detection. @register_patch def detect_encoding_patch(): def detect_encoding(path, binary_mode=False): if binary_mode: return return original(path) original = polib.detect_encoding polib.detect_encoding = detect_encoding # vim:ts=4 sw=4 et i18nspector-0.13.4/lib/paths.py0000644000000000000000000000254612312562472016226 0ustar00rootroot00000000000000# Copyright © 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' paths to code and data ''' import os basedir = os.path.normpath(os.path.join( os.path.dirname(__file__), os.path.pardir, '', )) datadir = os.path.join(basedir, 'data', '') def check(): os.stat(basedir) os.stat(datadir) # vim:ts=4 sw=4 et i18nspector-0.13.4/lib/moparser.py0000644000000000000000000001705012312562472016733 0ustar00rootroot00000000000000# Copyright © 2013, 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' MO file parser ''' # MO file format documentation: # * http://git.savannah.gnu.org/cgit/gettext.git/tree/gettext-runtime/intl/gmo.h?id=v0.18.3 # * http://git.savannah.gnu.org/cgit/gettext.git/tree/gettext-tools/src/read-mo.c?id=v0.18.3 # * http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html import re import struct import sys import polib from . import encodings little_endian_magic = b'\xDE\x12\x04\x95' big_endian_magic = little_endian_magic[::-1] class SyntaxError(Exception): pass class Parser(object): def __init__(self, path, *, encoding=None, check_for_duplicates=False, klass=None): self._encoding = encoding if check_for_duplicates: raise NotImplementedError with open(path, 'rb') as file: contents = file.read() view = memoryview(contents) if len(view) > 0: if sys.version_info >= (3, 3): # http://docs.python.org/3.3/whatsnew/3.3.html#pep-3118-new-memoryview-implementation-and-buffer-protocol-documentation # “Accessing a memoryview element with format ‘B’ (unsigned bytes) # now returns an integer […]. For returning a bytes object the view # must be cast to ‘c’ first.” view = view.cast('c') assert isinstance(view[0], bytes) self._view = view if klass is None: klass = polib.MOFile try: self.instance = klass( fpath=path, check_for_duplicates=False, ) self._parse() finally: del self._view def parse(self): return self.instance def _read_ints(self, at, n=1): begin = at end = at + 4 * n view = self._view if end > len(self._view): raise SyntaxError('truncated file') return struct.unpack( self._endian + 'I' * n, view[begin:end], ) def _parse(self): view = self._view magic = view[:4].tobytes() if magic == little_endian_magic: self._endian = '<' elif magic == big_endian_magic: self._endian = '>' else: raise SyntaxError('unexpected magic') [revision] = self._read_ints(at=4) major_revision, minor_revision = divmod(revision, 1 << 16) if major_revision > 1: raise SyntaxError('unexpected major revision number: {n}'.format(n=major_revision)) [n_strings] = self._read_ints(at=8) possible_hidden_strings = False if minor_revision > 1: # “an unexpected minor revision number means that the file can be # read but will not reveal its full contents” possible_hidden_strings = True elif minor_revision == 1: [n_sysdep_strings] = self._read_ints(at=36) if n_sysdep_strings > 0: possible_hidden_strings = True self.instance.possible_hidden_strings = possible_hidden_strings [msgid_offset, msgstr_offset] = self._read_ints(at=12, n=2) self._last_msgid = None for i in range(n_strings): entry = self._parse_entry(i, msgid_offset + 8 * i, msgstr_offset + 8 * i) self.instance.append(entry) def _parse_entry(self, i, msgid_offset, msgstr_offset): view = self._view [length, offset] = self._read_ints(at=msgid_offset, n=2) msgid = view[offset:offset+length].tobytes() try: if view[offset + length] != b'\0': raise SyntaxError('msgid is not null-terminated') except IndexError: raise SyntaxError('truncated file') msgids = msgid.split(b'\0', 2) msgid = msgids[0] if len(msgids) > 2: raise SyntaxError('unexpected null byte in msgid') [length, offset] = self._read_ints(at=msgstr_offset, n=2) msgstr = view[offset:offset+length].tobytes() try: if view[offset + length] != b'\0': raise SyntaxError('msgstr is not null-terminated') except IndexError: raise SyntaxError('truncated file') msgstrs = msgstr.split(b'\0') if len(msgids) == 1 and len(msgstrs) > 1: raise SyntaxError('unexpected null byte in msgstr') encoding = self._encoding if i == 0: if encoding is None and msgid == b'': # http://git.savannah.gnu.org/cgit/gettext.git/tree/gettext-runtime/intl/dcigettext.c?id=v0.18.3#n1106 match = re.search(b'charset=([^ \t\n]+)', msgstr) if match is not None: try: encoding = match.group(1).decode('ASCII') except UnicodeError: pass if encoding is None: encoding = 'ASCII' else: if not encodings.is_ascii_compatible_encoding(encoding): encoding = 'ASCII' self._encoding = encoding else: if msgids == self._last_msgid: raise SyntaxError('duplicate message definition') elif msgid < self._last_msgid: raise SyntaxError('messages are not sorted') self._last_msgid = msgid assert encoding is not None msgid, *msgctxt = msgid.split(b'\x04', 1) kwargs = dict(msgid=msgid.decode(encoding)) if msgctxt: [msgctxt] = msgctxt kwargs.update(msgctxt=msgctxt.decode(encoding)) if len(msgids) == 1: assert [msgstr] == msgstrs kwargs.update(msgstr=msgstr.decode(encoding)) else: assert len(msgids) == 2 assert len(msgstrs) >= 1 kwargs.update(msgid_plural=msgids[1].decode(encoding)) kwargs.update(msgstr_plural= {i: s.decode(encoding) for i, s in enumerate(msgstrs)} ) entry = polib.MOEntry(**kwargs) entry.occurrences = () entry.flags = () # https://bitbucket.org/izi/polib/issue/47 entry.translated = lambda: True return entry __all__ = ['Parser', 'SyntaxError'] def main(): import argparse ap = argparse.ArgumentParser(description='msgunfmt(1) replacement') ap.add_argument('files', metavar='', nargs='+') options = ap.parse_args() for path in options.files: parser = Parser(path) print(parser.parse()) if __name__ == '__main__': main() else: del main # vim:ts=4 sw=4 et i18nspector-0.13.4/lib/misc.py0000644000000000000000000000574212312562472016043 0ustar00rootroot00000000000000# Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' miscellanea ''' import datetime import errno import shlex def is_sorted(iterable): # It's not very efficient, but should be enough for our purposes. lst1 = list(iterable) lst2 = sorted(lst1) return lst1 == lst2 class DataIntegrityError(Exception): pass def check_sorted(iterable, exception=DataIntegrityError): if not is_sorted(iterable): raise exception() class OSRelease(object): ''' /etc/os-release parser File format documentation: http://www.freedesktop.org/software/systemd/man/os-release.html ''' def __init__(self, path='/etc/os-release'): self._id = None self._id_like = () try: file = open(path, 'rt', encoding='UTF-8') except EnvironmentError as exc: if exc.errno == errno.ENOENT: return raise with file: for line in file: self._parse_line(line) def _parse_line(self, line): try: name, value = line.split('=', 1) [value] = shlex.split(value) except ValueError: return if name == 'ID': self._id = value elif name == 'ID_LIKE': self._id_like = frozenset(value.split()) def is_like(self, ident): if ident is None: raise TypeError('ident must not be None') if self._id == ident: return True return ident in self._id_like def utc_now(): now = datetime.datetime.now() now = now.replace(tzinfo=datetime.timezone.utc) return now def format_range(rng, *, max): last = rng[-1] result = [] if max < 4: raise ValueError('max must be >= 4') for i in rng: if len(result) < max: result += [i] else: result[-2:] = ['...', str(last)] break return ', '.join(map(str, result)) # vim:ts=4 sw=4 et i18nspector-0.13.4/lib/ling.py0000644000000000000000000002537612312562472016046 0ustar00rootroot00000000000000# Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' language information registry ''' import configparser import os import re import unicodedata from . import misc from . import paths def _munch_language_name(s): # Normalize whitespace: s = ' '.join(s.split()) # Normalize capitalization: s = s.lower() # Strip accent marks etc.: s = unicodedata.normalize('NFD', s).encode('ASCII', 'ignore').decode() return s class LanguageError(ValueError): pass class LanguageSyntaxError(LanguageError): pass class FixingLanguageCodesFailed(LanguageError): pass class FixingLanguageEncodingFailed(LanguageError): pass class Language(object): def __init__(self, language_code, territory_code=None, encoding=None, modifier=None): self.language_code = language_code if language_code is None: raise TypeError('language_code must not be None') # self.territory_code = territory_code self.encoding = None if encoding is not None: self.encoding = encoding.upper() self.modifier = modifier def _get_tuple(self): return ( self.language_code, self.territory_code, self.encoding, self.modifier ) def clone(self): return Language(*self._get_tuple()) def __eq__(self, other): if not isinstance(other, Language): return NotImplemented return self._get_tuple() == other._get_tuple() def __ne__(self, other): return not self == other def is_almost_equal(self, other): if not isinstance(other, Language): raise TypeError self_clone = self.clone() self_clone.remove_principal_territory_code() other_clone = other.clone() other_clone.remove_principal_territory_code() return self_clone == other_clone def fix_codes(self): fixed = None ll = self.language_code ll = _lookup_language_code(ll) if ll is None: # TODO: Try to guess correct language code. raise FixingLanguageCodesFailed() elif ll != self.language_code: fixed = True cc = self.territory_code if cc is not None: cc = lookup_territory_code(cc) if cc is None: # TODO: Try to guess correct territory code. raise FixingLanguageCodesFailed() elif cc != self.territory_code: # This shouldn't really happen, but better safe than sorry. raise ValueError # # TODO: ll_CC could be still incorrect, even when both ll and CC are # correct. self.language_code = ll self.territory_code = cc return fixed def get_principal_territory_code(self): ll = self.language_code assert ll is not None return _get_principal_territory_code(ll) def remove_principal_territory_code(self): cc = self.territory_code if cc is None: return default_cc = self.get_principal_territory_code() if cc == default_cc: self.territory_code = None return True def remove_encoding(self): if self.encoding is None: return self.encoding = None return True def remove_nonlinguistic_modifier(self): if self.modifier == 'euro': self.modifier = None return True return def get_plural_forms(self): result = None if self.territory_code is not None: code = self._simple_format() result = _get_plural_forms(code) if result is None: code = self._simple_format(territory=False) result = _get_plural_forms(code) return result def get_unrepresentable_characters(self, encoding, strict=False): characters = None if self.territory_code is not None: code = self._simple_format() characters = _get_characters(code, self.modifier, strict=strict) if characters is None: code = self._simple_format(territory=False) characters = _get_characters(code, self.modifier, strict=strict) if characters is None: return result = [] try: # If iconv(1) is used to implement an encoding, there's a huge # overhead per encode() call. To reduce number of such calls, # optimize the common case of all characters being representable. ''.join(characters).encode(encoding) except UnicodeError: pass else: return result for character in characters: try: character.encode(encoding) except UnicodeError as exc: result += [character] if exc.reason.startswith('iconv:'): # Avoid further calls to iconv(1): break return result def _simple_format(self, territory=True): s = self.language_code if territory and self.territory_code is not None: s += '_' + self.territory_code return s def __str__(self): s = self.language_code if self.territory_code is not None: s += '_' + self.territory_code if self.encoding is not None: s += '.' + self.encoding if self.modifier is not None: s += '@' + self.modifier return s def _read_iso_codes(): # ISO language/territory codes: path = os.path.join(paths.datadir, 'iso-codes') cp = configparser.ConfigParser(interpolation=None, default_section='') cp.read(path, encoding='UTF-8') iso_639 = cp['language-codes'] misc.check_sorted(iso_639) _iso_639 = {} for lll, ll in iso_639.items(): if ll: _iso_639[ll] = ll _iso_639[lll] = ll else: _iso_639[lll] = lll iso_3166 = cp['territory-codes'] misc.check_sorted(iso_3166) _iso_3166 = frozenset(cc.upper() for cc in iso_3166.keys()) return (_iso_639, _iso_3166) [_iso_639, _iso_3166] = _read_iso_codes() def _read_primary_languages(): # Hand-edited linguistic data: path = os.path.join(paths.datadir, 'languages') cp = configparser.ConfigParser(interpolation=None, default_section='') cp.read(path, encoding='UTF-8') _primary_languages = {name: sect for name, sect in cp.items() if sect.name} _name_to_code = {} misc.check_sorted(cp) for language, section in cp.items(): if not language: continue for name in section['names'].splitlines(): name = _munch_language_name(name) if name: if name in _name_to_code: raise misc.DataIntegrityError _name_to_code[name] = language return _primary_languages, _name_to_code def _check_primary_languages_coverage(): # Check if primary languages have full ISO 639-1 coverage: for ll in _iso_639: if len(ll) > 2: continue try: _primary_languages[ll] except LookupError: # raise misc.DataIntegrityError [_primary_languages, _name_to_code] = _read_primary_languages() _check_primary_languages_coverage() def _lookup_language_code(language): return _iso_639.get(language) def lookup_territory_code(cc): if cc in _iso_3166: return cc def get_language_for_name(name): parse = parse_language _name = _munch_language_name(name) try: return parse(_name_to_code[_name]) except KeyError: pass if ';' in _name: for subname in _name.split(';'): subname = subname.strip() try: return parse(_name_to_code[subname]) except LookupError: pass if ',' in _name: subname = ' '.join(map(str.strip, _name.split(',', 1)[::-1])) try: return parse(_name_to_code[subname]) except LookupError: pass results = set() for subname in _name.split(','): subname = subname.strip() result = _name_to_code.get(subname) results.add(result) if len(results) == 1: return parse(results.pop()) raise LookupError(name) _language_regexp = re.compile(r''' ^ ( [a-z]{2,} ) (?: _ ( [A-Z]{2,} ) )? (?: [.] ( [a-zA-Z0-9+-]+ ) )? (?: @ ( [a-z]+) )? $''', re.VERBOSE) def parse_language(s): match = _language_regexp.match(s) if match is None: raise LanguageSyntaxError return Language(*match.groups()) def get_primary_languages(): return iter(_primary_languages) def _get_plural_forms(language): try: section = _primary_languages[language] except KeyError: return plural_forms = section.get('plural-forms') if plural_forms is None: return return [ s.strip() for s in plural_forms.splitlines() if s and not s.isspace() ] def _get_principal_territory_code(language): try: section = _primary_languages[language] except KeyError: return return section.get('principal-territory') def _get_characters(language, modifier=None, strict=True): try: section = _primary_languages[language] except KeyError: return section_name = 'characters' if modifier is not None: section_name += '@{}'.format(modifier) result = section.get(section_name) if result is None: return if strict: return [ ch.strip('()') for ch in result.split() ] else: return [ ch for ch in result.split() if not (ch.startswith('(') and ch.endswith(')')) ] # vim:ts=4 sw=4 et i18nspector-0.13.4/lib/intexpr.py0000644000000000000000000002653412312562472016603 0ustar00rootroot00000000000000# Copyright © 2012, 2013, 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' squeeze Python abstract syntax trees into C integer expressions semantics ''' import ast class BaseEvaluator(object): def __init__(self, node): class context: pass self._ctxt = context self._node = node def __call__(self): node = self._node assert isinstance(node, ast.Expr) return self._visit_expr(node) def _visit(self, node, *args): try: fn = getattr(self, '_visit_' + type(node).__name__.lower()) except KeyError: # raise NotImplementedError(type(node).__name__) return fn(node, *args) def _visit_expr(self, node): [node] = ast.iter_child_nodes(node) return self._visit(node) # binary operators # ================ def _visit_binop(self, node): x = self._visit(node.left) if x is None: return y = self._visit(node.right) if y is None: return return self._visit(node.op, x, y) # unary operators # =============== def _visit_unaryop(self, node): x = self._visit(node.operand) if x is None: return return self._visit(node.op, x) # comparison operators # ==================== def _visit_compare(self, node): # This one is tricky because in C equality comparison operators have # lower priority that inequality comparison operators. This is unlike # Python, in which they have the same priority. assert len(node.comparators) == len(node.ops) new_vals = [] new_ops = [] # high priority: <, <=, >, >= left = self._visit(node.left) if left is None: return for op, right in zip(node.ops, node.comparators): right = self._visit(right) if right is None: return if isinstance(op, (ast.Eq, ast.NotEq)): new_vals += [left] new_ops += [op] left = right else: left = self._visit(op, left, right) new_vals += [left] assert len(new_vals) == len(new_ops) + 1 # low priority: ==, != new_vals = iter(new_vals) left = next(new_vals) for op, right in zip(new_ops, new_vals): left = self._visit(op, left, right) return left # boolean operators # ================= def _visit_boolop(self, node): return self._visit(node.op, *node.values) class Evaluator(BaseEvaluator): def __init__(self, node, n, *, bits): super().__init__(node) self._ctxt.n = n self._ctxt.max = 1 << bits def _check_overflow(self, n): if n < 0: raise OverflowError(n) if n >= self._ctxt.max: raise OverflowError(n) return n # binary operators # ================ def _visit_add(self, node, x, y): return self._check_overflow(x + y) def _visit_sub(self, node, x, y): return self._check_overflow(x - y) def _visit_mult(self, node, x, y): return self._check_overflow(x * y) def _visit_div(self, node, x, y): return x // y def _visit_mod(self, node, x, y): return x % y # unary operators # =============== def _visit_invert(self, node, x): return int(not x) # comparison operators # ==================== def _visit_gte(self, node, x, y): return int(x >= y) def _visit_gt(self, node, x, y): return int(x > y) def _visit_lte(self, node, x, y): return int(x <= y) def _visit_lt(self, node, x, y): return int(x < y) def _visit_eq(self, node, x, y): return int(x == y) def _visit_noteq(self, node, x, y): return int(x != y) # boolean operators # ================= def _visit_and(self, node, *args): for arg in args: if self._visit(arg) == 0: return 0 return 1 def _visit_or(self, node, *args): for arg in args: if self._visit(arg) != 0: return 1 return 0 # if-then-else expression # ======================= def _visit_ifexp(self, node): test = self._visit(node.test) if test: return self._visit(node.body) else: return self._visit(node.orelse) # contants, variables # =================== def _visit_num(self, node): return self._check_overflow(node.n) def _visit_name(self, node): return self._check_overflow(self._ctxt.n) class CodomainEvaluator(BaseEvaluator): def __init__(self, node, *, bits): class context: pass context.max = 1 << bits self._ctxt = context self._node = node def __call__(self): node = self._node assert isinstance(node, ast.Expr) return self._visit_expr(node) def _visit(self, node, *args): try: fn = getattr(self, '_visit_' + type(node).__name__.lower()) except KeyError: # raise NotImplementedError(type(node).__name__) return fn(node, *args) def _visit_expr(self, node): [node] = ast.iter_child_nodes(node) return self._visit(node) # binary operators # ================ def _visit_add(self, node, x, y): z = ( x[0] + y[0], min(x[1] + y[1], self._ctxt.max - 1) ) if z[0] > z[1]: return return z def _visit_sub(self, node, x, y): z = ( max(x[0] - y[1], 0), x[1] - y[0] ) if z[0] > z[1]: return return z def _visit_mult(self, node, x, y): z = ( x[0] * y[0], min(x[1] * y[1], self._ctxt.max - 1) ) if z[0] > z[1]: return return z def _visit_div(self, node, x, y): if y == (0, 0): # division by zero return assert y[1] > 0 return ( x[0] // y[1], x[1] // max(y[0], 1), ) def _visit_mod(self, node, x, y): if y == (0, 0): # division by zero return assert y[1] > 0 if x[1] < y[0]: # i % j == i if i < j return x return (0, min(x[1], y[1] - 1)) # unary operators # =============== def _visit_invert(self, node, x): if x[0] > 0: return (0, 0) elif x == (0, 0): return (1, 1) else: return (0, 1) # comparison operators # ==================== def _visit_gte(self, node, x, y): assert (x is not None) and (y is not None) return ( x[0] >= y[1], x[1] >= y[0], ) def _visit_gt(self, node, x, y): assert (x is not None) and (y is not None) return ( x[0] > y[1], x[1] > y[0], ) def _visit_lte(self, node, x, y): assert (x is not None) and (y is not None) return ( x[1] <= y[0], x[0] <= y[1], ) def _visit_lt(self, node, x, y): assert (x is not None) and (y is not None) return ( x[1] < y[0], x[0] < y[1], ) def _visit_eq(self, node, x, y): assert (x is not None) and (y is not None) if x[0] == x[1] == y[0] == y[1]: return (1, 1) if x[0] <= y[0] <= x[1]: return (0, 1) if y[0] <= x[0] <= y[1]: return (0, 1) return (0, 0) def _visit_noteq(self, node, x, y): assert (x is not None) and (y is not None) if x[0] == x[1] == y[0] == y[1]: return (0, 0) if x[0] <= y[0] <= x[1]: return (0, 1) if y[0] <= x[0] <= y[1]: return (0, 1) return (1, 1) # boolean operators # ================= def _visit_and(self, node, *args): r = (1, 1) for arg in args: assert r != (0, 0) x = self._visit(arg) if x is None: if r == (0, 1): return (0, 0) else: return elif x == (0, 0): return x elif x[0] >= 1: pass else: assert (x[0] == 0) and (x[1] > 0) r = (0, 1) return r def _visit_or(self, node, *args): r = (0, 0) for arg in args: assert r != (1, 1) x = self._visit(arg) if x is None: if r == (0, 1): return (1, 1) else: return elif x[0] >= 1: return (1, 1) elif x == (0, 0): pass else: assert (x[0] == 0) and (x[1] > 0) r = (0, 1) return r # if-then-else expression # ======================= def _visit_ifexp(self, node): test = self._visit(node.test) if test is None: return x = y = None if test[1] > 0: x = self._visit(node.body) if test[0] == 0: y = self._visit(node.orelse) if x is None: return y if y is None: return x return ( min(x[0], y[0]), max(x[1], y[1]), ) # contants, variables # =================== def _visit_num(self, node): n = node.n if (n < 0) or (n >= self._ctxt.max): return return (n, n) def _visit_name(self, node): return (0, self._ctxt.max - 1) class Expression(object): def __init__(self, s): module = ast.parse('({})'.format(s), filename='') assert isinstance(module, ast.Module) [node] = ast.iter_child_nodes(module) assert isinstance(node, ast.Expr) self._node = node def __call__(self, n, *, bits=32): ''' return f(n) ''' e = Evaluator(self._node, n, bits=bits) return e() def codomain(self, *, bits=32): ''' return * (i, j) such that for every n, f(n) ∈ {i, i+1, …, j} * or None ''' e = CodomainEvaluator(self._node, bits=bits) return e() # vim:ts=4 sw=4 et i18nspector-0.13.4/lib/iconv.py0000644000000000000000000002365212312562472016226 0ustar00rootroot00000000000000# Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' string encoding and decoding using iconv(3), with a fallback to iconv(1) ''' import ctypes import errno import os import subprocess as ipc import re import sys default_encoding = sys.getdefaultencoding() _boring_iconv_stderr = re.compile('\nTry .+ for more information[.]$') _libc = ctypes.CDLL(None, use_errno=True) try: _iconv_open = _libc.iconv_open _iconv_close = _libc.iconv_close _iconv = _libc.iconv except AttributeError: _iconv = _iconv_open = _iconv_close = None else: _iconv_open.argtypes = [ctypes.c_char_p, ctypes.c_char_p] _iconv_open.restype = ctypes.c_void_p _iconv_close.argtypes = [ctypes.c_void_p] _iconv_close.restype = ctypes.c_int _iconv.argtypes = ( [ctypes.c_void_p] + [ctypes.POINTER(ctypes.POINTER(ctypes.c_char)), ctypes.POINTER(ctypes.c_size_t)] * 2 ) _iconv.restype = ctypes.c_size_t def _popen(*args): def set_lc_all_c(): os.environ['LC_ALL'] = 'C' # return ipc.Popen(args, stdin=ipc.PIPE, stdout=ipc.PIPE, stderr=ipc.PIPE, preexec_fn=set_lc_all_c, ) def encode(input: str, encoding=default_encoding, errors='strict'): if not isinstance(input, str): raise TypeError('input must be str, not {tp}'.format(tp=type(input).__name__)) if not isinstance(encoding, str): raise TypeError('encoding must be str, not {tp}'.format(tp=type(encoding).__name__)) if not isinstance(errors, str): raise TypeError('errors must be str, not {tp}'.format(tp=type(errors).__name__)) if len(input) == 0: return b'' if errors != 'strict': raise NotImplementedError('error handler {e!r} is not implemented'.format(e=errors)) return _encode(input, encoding=encoding) def _encode_dl(input: str, *, encoding): if sys.maxunicode < (1 << 16): uencoding = 'UTF-16LE' uwidth = 2 else: uencoding = 'UTF-32LE' uwidth = 4 binput = bytes(input, encoding=uencoding) assert len(binput) == len(input) * uwidth cd = _iconv_open(bytes(encoding, 'ASCII'), bytes(uencoding, 'ASCII')) assert isinstance(cd, int) if cd == ctypes.c_void_p(-1).value: rc = ctypes.get_errno() raise OSError(rc, os.strerror(rc)) try: c_input = ctypes.c_char_p(binput) output_len = len(input) while True: inbuf = ctypes.cast(c_input, ctypes.POINTER(ctypes.c_char)) inbytesleft = ctypes.c_size_t(len(binput)) assert inbytesleft.value == len(binput) # no overflow outbuf = ctypes.create_string_buffer(output_len) outbytesleft = ctypes.c_size_t(output_len) assert outbytesleft.value == output_len # no overflow rc = _iconv(cd, None, None, None, None) if rc == ctypes.c_size_t(-1).value: rc = ctypes.get_errno() raise OSError(rc, os.strerror(rc)) inbufptr = ctypes.pointer(ctypes.cast(inbuf, ctypes.POINTER(ctypes.c_char))) outbufptr = ctypes.pointer(ctypes.cast(outbuf, ctypes.POINTER(ctypes.c_char))) rc = _iconv(cd, inbufptr, ctypes.byref(inbytesleft), outbufptr, ctypes.byref(outbytesleft), ) if rc != ctypes.c_size_t(-1).value: rc = _iconv(cd, None, None, outbufptr, ctypes.byref(outbytesleft), ) if rc == ctypes.c_size_t(-1).value: rc = ctypes.get_errno() if rc == errno.E2BIG: output_len *= 2 continue elif rc in {errno.EILSEQ, errno.EINVAL}: begin = len(input) - inbytesleft.value // uwidth raise UnicodeEncodeError( encoding, input, begin, begin + 1, os.strerror(errno.EILSEQ), ) raise OSError(rc, os.strerror(rc)) assert inbytesleft.value == 0, '{n} bytes left'.format(n=inbytesleft.value) output_len -= outbytesleft.value return outbuf[:output_len] finally: rc = _iconv_close(cd) if rc != 0: rc = ctypes.get_errno() raise OSError(rc, os.strerror(rc)) def _encode_cli(input, *, encoding): child = _popen('iconv', '-f', 'UTF-8', '-t', encoding) (stdout, stderr) = child.communicate(input.encode('UTF-8')) if stderr != b'': stderr = stderr.decode('ASCII', 'replace') stderr = _boring_iconv_stderr.sub('', stderr) raise UnicodeEncodeError(encoding, input, # .object 0, # .begin len(input), # .end stderr.strip() # .reason ) return stdout _encode = _encode_dl if _iconv is not None else _encode_cli def decode(input: bytes, encoding=default_encoding, errors='strict'): if not isinstance(input, bytes): raise TypeError('input must be bytes, not {tp}'.format(tp=type(input).__name__)) if not isinstance(encoding, str): raise TypeError('encoding must be str, not {tp}'.format(tp=type(encoding).__name__)) if not isinstance(errors, str): raise TypeError('errors must be str, not {tp}'.format(tp=type(errors).__name__)) if len(input) == 0: return '' if errors != 'strict': raise NotImplementedError('error handler {e!r} is not implemented'.format(e=errors)) return _decode(input, encoding=encoding) def _decode_dl(input: bytes, *, encoding): cd = _iconv_open(b'WCHAR_T', bytes(encoding, 'ASCII')) assert isinstance(cd, int) if cd == ctypes.c_void_p(-1).value: rc = ctypes.get_errno() raise OSError(rc, os.strerror(rc)) try: c_input = ctypes.c_char_p(input) output_len = len(input) while True: inbuf = ctypes.cast(c_input, ctypes.POINTER(ctypes.c_char)) inbytesleft = ctypes.c_size_t(len(input)) assert inbytesleft.value == len(input) # no overflow outbuf = ctypes.create_unicode_buffer(output_len) outbytesleft = ctypes.c_size_t(output_len) # no overflow assert outbytesleft.value == output_len rc = _iconv(cd, None, None, None, None) if rc == ctypes.c_size_t(-1).value: rc = ctypes.get_errno() raise OSError(rc, os.strerror(rc)) inbufptr = ctypes.pointer(ctypes.cast(inbuf, ctypes.POINTER(ctypes.c_char))) outbufptr = ctypes.pointer(ctypes.cast(outbuf, ctypes.POINTER(ctypes.c_char))) rc = _iconv(cd, inbufptr, ctypes.byref(inbytesleft), outbufptr, ctypes.byref(outbytesleft), ) if rc != ctypes.c_size_t(-1).value: rc = _iconv(cd, None, None, outbufptr, ctypes.byref(outbytesleft), ) if rc == ctypes.c_size_t(-1).value: rc = ctypes.get_errno() if rc == errno.E2BIG: output_len *= 2 continue elif rc in {errno.EILSEQ, errno.EINVAL}: begin = len(input) - inbytesleft.value for end in range(begin + 1, len(input)): # Assume that the encoding can be synchronized on ASCII characters. # That's not necessarily true for _every_ encoding, but oh well. if input[end] < 0x80: break else: end = len(input) raise UnicodeDecodeError( encoding, input, begin, end, os.strerror(errno.EILSEQ), ) raise OSError(rc, os.strerror(rc)) assert inbytesleft.value == 0, '{n} bytes left'.format(n=inbytesleft.value) output_len -= outbytesleft.value assert output_len % ctypes.sizeof(ctypes.c_wchar) == 0 unicode_output_len = output_len // ctypes.sizeof(ctypes.c_wchar) return outbuf[:unicode_output_len] finally: rc = _iconv_close(cd) if rc != 0: rc = ctypes.get_errno() raise OSError(rc, os.strerror(rc)) def _decode_cli(input, *, encoding): child = _popen('iconv', '-f', encoding, '-t', 'UTF-8') (stdout, stderr) = child.communicate(input) if stderr != b'': stderr = stderr.decode('ASCII', 'replace') stderr = _boring_iconv_stderr.sub('', stderr) raise UnicodeDecodeError(encoding, input, # .object 0, # .begin len(input), # .end stderr.strip() # .reason ) return stdout.decode('UTF-8') _decode = _decode_dl if _iconv is not None else _decode_cli __all__ = ['encode', 'decode'] # vim:ts=4 sw=4 et i18nspector-0.13.4/lib/gettext.py0000644000000000000000000002001612312562472016563 0ustar00rootroot00000000000000# Copyright © 2012, 2013, 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' gettext header support: - header field names registry - date parser - plural expressions parser - string formats registry ''' import configparser import datetime import functools import os import re from . import intexpr from . import misc from . import paths # ============= # Header fields # ============= def _read_header_fields(): path = os.path.join(paths.datadir, 'header-fields') with open(path, 'rt', encoding='ASCII') as file: fields = [ s.rstrip() for s in file if s.rstrip() and not s.startswith('#') ] misc.check_sorted(fields) return frozenset(fields) header_fields = _read_header_fields() # ========================== # Header and message parsing # ========================== is_valid_field_name = re.compile(r'^[\x21-\x39\x3b-\x7e]+$').match # http://tools.ietf.org/html/rfc5322#section-3.6.8 def parse_header(s): lines = s.split('\n') if lines[-1] == '': lines.pop() for line in lines: key, *values = line.split(':', 1) if values and is_valid_field_name(key): assert len(values) == 1 value = values[0].strip(' \t') yield {key: value} else: yield line search_for_conflict_marker = re.compile(r'^#-#-#-#-# .+ #-#-#-#-#$', re.MULTILINE).search # http://git.savannah.gnu.org/cgit/gettext.git/tree/gettext-tools/src/msgl-cat.c?id=v0.18.3#n590 # http://www.gnu.org/software/gettext/manual/html_node/Creating-Compendia.html#Creating-Compendia # ============ # Plural forms # ============ # http://git.savannah.gnu.org/cgit/gettext.git/tree/gettext-runtime/intl/plural.y?id=v0.18.3#n132 class PluralFormsSyntaxError(Exception): pass class PluralExpressionSyntaxError(PluralFormsSyntaxError): pass _plural_exp_tokens = [ (r'[0-9]+', None), (r'[=!]=', None), (r'!', 'not'), (r'&&', 'and'), (r'[|][|]', 'or'), (r'[<>]=?', None), (r'[*/%]', None), (r'[+-]', None), (r'n', None), (r'[?:]', None), (r'[()]', None), (r'[ \t]', None), (r'.', '_'), # junk ] _plural_exp_token_re = '|'.join( chunk if repl is None else '(?P<{}>{})'.format(repl, chunk) for chunk, repl in _plural_exp_tokens ) _plural_exp_token_re = re.compile(_plural_exp_token_re) def _plural_exp_tokenize(s): prev_value = ' ' for match in _plural_exp_token_re.finditer(s): for pytoken, ctoken in match.groupdict().items(): if ctoken is not None: break value = match.group(0) if ctoken is not None: if pytoken == '_': # junk raise PluralExpressionSyntaxError(value) if pytoken == 'not': # priority of “not” in Python is too low to be used here pytoken = '~' yield ' {} '.format(pytoken) elif value in {'+', '-'}: if prev_value in {'n', ')'} or prev_value.isdigit(): yield value else: # unary plus and unary minus are not supported raise PluralExpressionSyntaxError(value) else: yield value if not value.isspace(): prev_value = value _ifelse_re = re.compile(r'(.*?)[?](.*?):(.*)') def _subst_ifelse(match): return '({true} if {cond} else {false})'.format( cond=match.group(1), true=match.group(2), false=_subst_ifelse(match.group(3)) ) # The magic below makes _subst_ifelse() act on strings rather than match # objects. _subst_ifelse = functools.partial(_ifelse_re.sub, _subst_ifelse) def parse_plural_expression(s): stack = [''] for token in _plural_exp_tokenize(s): if token == '(': stack += [''] elif token == ')': if len(stack) <= 1: raise PluralExpressionSyntaxError s = _subst_ifelse(stack.pop()) stack[-1] += '({})'.format(s) else: stack[-1] += token if len(stack) != 1: raise PluralExpressionSyntaxError [s] = stack s = _subst_ifelse(s) try: fn = intexpr.Expression(s) except SyntaxError: raise PluralExpressionSyntaxError return fn _parse_plural_forms = re.compile(r'^nplurals=([1-9][0-9]*);[ \t]*plural=([^;]+);?$').match def parse_plural_forms(s): match = _parse_plural_forms(s) if match is None: raise PluralFormsSyntaxError n = int(match.group(1), 10) expr = parse_plural_expression(match.group(2)) return (n, expr) # ===== # Dates # ===== class DateSyntaxError(Exception): pass class BoilerplateDate(DateSyntaxError): pass def _read_timezones(): path = os.path.join(paths.datadir, 'timezones') cp = configparser.ConfigParser(interpolation=None, default_section='') cp.optionxform = str cp.read(path, encoding='ASCII') return { abbrev: offsets.split() for abbrev, offsets in cp['timezones'].items() } _timezones = _read_timezones() _tz_re = '|'.join(re.escape(tz) for tz in _timezones) _parse_date = re.compile(''' ^ ( [0-9]{4}-[0-9]{2}-[0-9]{2} ) # YYYY-MM-DD (?: \s+ | T ) ( [0-9]{2}:[0-9]{2} ) # hh:mm (?: : [0-9]{2} )? # ss \s* (?: (?: GMT | UTC )? ( [+-] [0-9]{2} ) :? ( [0-9]{2} ) # ZZzz | [+]? (''' + _tz_re + ''') ) ? $ ''', re.VERBOSE).match boilerplate_date = 'YEAR-MO-DA HO:MI+ZONE' _search_for_date_boilerplate = re.compile(''' ^ YEAR - | - MO - | - DA \s | \s HO : | : MI (?:[+]|$) | [+] ZONE $ ''', re.VERBOSE).search def fix_date_format(s, *, tz_hint=None): s = s.strip() if _search_for_date_boilerplate(s): raise BoilerplateDate if tz_hint is not None: datetime.datetime.strptime(tz_hint, '%z') # just check syntax match = _parse_date(s) if match is None: raise DateSyntaxError (date, time, zhour, zminute, zabbr) = match.groups() if (zhour is not None) and (zminute is not None): zone = zhour + zminute elif zabbr is not None: try: [zone] = _timezones[zabbr] except ValueError: raise DateSyntaxError('ambiguous timezone abbreviation: ' + zabbr) elif tz_hint is not None: zone = tz_hint else: raise DateSyntaxError s = '{} {}{}'.format(date, time, zone) assert len(s) == 21, 'len({!r}) != 21'.format(s) parse_date(s) # just check syntax return s def parse_date(s): try: return datetime.datetime.strptime(s, '%Y-%m-%d %H:%M%z') except ValueError as exc: raise DateSyntaxError(exc) epoch = datetime.datetime(1995, 7, 2, tzinfo=datetime.timezone.utc) # ============== # String formats # ============== def _read_string_formats(): path = os.path.join(paths.datadir, 'string-formats') with open(path, 'rt', encoding='ASCII') as file: fields = [ s.rstrip() for s in file if s.rstrip() and not s.startswith('#') ] misc.check_sorted(fields) return frozenset(fields) string_formats = _read_string_formats() # vim:ts=4 sw=4 et i18nspector-0.13.4/lib/encodings.py0000644000000000000000000001633212312562472017056 0ustar00rootroot00000000000000# Copyright © 2012, 2013, 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' - encoding information registry - codecs for unusual encodings ''' import codecs import configparser import encodings.aliases as encoding_aliases import errno import functools import itertools import os import unicodedata from . import iconv from . import misc from . import paths class EncodingLookupError(LookupError): def __init__(self, encoding): return LookupError.__init__(self, 'unknown encoding: ' + encoding) def _not_implemented(*args, **kwargs): raise NotImplementedError def charmap_encoding(encoding): def encode(input, errors='strict'): return codecs.charmap_encode(input, errors, encoding_table) def decode(input, errors='strict'): return codecs.charmap_decode(input, errors, decoding_table) path = os.path.join(paths.datadir, 'charmaps', encoding.upper()) try: file = open(path, 'rb') except IOError as exc: if exc.errno == errno.ENOENT: raise EncodingLookupError(encoding) raise with file: decoding_table = file.read() decoding_table = decoding_table.decode('UTF-8') encoding_table = codecs.charmap_build(decoding_table) return codecs.CodecInfo( encode=encode, decode=decode, streamreader=_not_implemented, streamwriter=_not_implemented, incrementalencoder=_not_implemented, incrementaldecoder=_not_implemented, name=encoding, ) def iconv_encoding(encoding): def encode(input, errors='strict'): output = iconv.encode(input, encoding=encoding, errors=errors) return output, len(input) def decode(input, errors='strict'): output = iconv.decode(bytes(input), encoding=encoding, errors=errors) return output, len(input) return codecs.CodecInfo( encode=encode, decode=decode, streamreader=_not_implemented, streamwriter=_not_implemented, incrementalencoder=_not_implemented, incrementaldecoder=_not_implemented, name=encoding, ) _interesting_ascii_bytes = bytes(itertools.chain([ 0, # NUL 4, # EOT 7, # BEL 8, # BS 9, # HT 10, # LF 11, # VT 12, # FF 13, # CR 27, # ESC ], range(32, 127))) _interesting_ascii_str = _interesting_ascii_bytes.decode() def _read_encodings(): path = os.path.join(paths.datadir, 'encodings') cp = configparser.ConfigParser(interpolation=None, default_section='') cp.read(path, encoding='UTF-8') e2c = {} c2e = {} for encoding, extra in cp['portable-encodings'].items(): e2c[encoding] = None if extra == '': pycodec = codecs.lookup(encoding) e2c[encoding] = pycodec c2e.setdefault(pycodec.name, encoding) elif extra == 'not-python': pass else: raise misc.DataIntegrityError extra_encodings = { key.lower() for key, value in cp['extra-encodings'].items() } return (e2c, c2e, extra_encodings) [_portable_encodings, _pycodec_to_encoding, _extra_encodings] = _read_encodings() def _read_control_characters(): path = os.path.join(paths.datadir, 'control-characters') cp = configparser.ConfigParser(interpolation=None, default_section='') cp.read(path, encoding='UTF-8') for section in cp.values(): if not section.name: continue misc.check_sorted(section) for code, name in section.items(): if len(code) != 2: raise misc.DataIntegrityError code = chr(int(code, 16)) if unicodedata.category(code) != 'Cc': raise misc.DataIntegrityError if name.upper() != name: raise misc.DataIntegrityError yield (code, name) _control_character_names = dict(_read_control_characters()) def get_portable_encodings(python=True): return ( encoding for encoding, codec in _portable_encodings.items() if (not python) or (codec is not None) ) def is_portable_encoding(encoding, python=True): encoding = encoding.lower() if encoding.startswith('iso_'): encoding = 'iso-' + encoding[4:] if python: return _portable_encodings.get(encoding, None) is not None else: return encoding in _portable_encodings def propose_portable_encoding(encoding, python=True): # Note that the "python" argument is never used. # Only encodings supported by Python are proposed. try: pycodec = codecs.lookup(encoding) new_encoding = _pycodec_to_encoding[pycodec.name] except LookupError: return assert is_portable_encoding(new_encoding, python=True) return new_encoding.upper() def is_ascii_compatible_encoding(encoding, *, missing_ok=True): try: return ( _interesting_ascii_bytes.decode(encoding) == _interesting_ascii_str ) except UnicodeDecodeError: return False except LookupError: pass except Exception: pass if missing_ok: return False else: raise EncodingLookupError(encoding) def _codec_search_function(encoding): if _portable_encodings.get(encoding, False) is None: # portable according to gettext documentation # but not supported directly by Python pass elif encoding in _extra_encodings: # non-portable, but used by real-world software pass else: return try: return charmap_encoding(encoding) except EncodingLookupError: return iconv_encoding(encoding) @functools.lru_cache(maxsize=1) def install_extra_encodings(): codecs.register(_codec_search_function) for enc_name in _portable_encodings: if enc_name.startswith('iso-'): suffix = enc_name[4:].replace('-', '_') encoding_aliases.aliases.setdefault(suffix, 'iso' + suffix) def get_character_name(ch): try: return unicodedata.name(ch) except ValueError: if unicodedata.category(ch) == 'Cn': return 'non-character' name = _control_character_names.get(ch) if name is None: raise return 'control character ' + name # vim:ts=4 sw=4 et i18nspector-0.13.4/lib/domains.py0000644000000000000000000000376512312562472016545 0ustar00rootroot00000000000000# Copyright © 2013, 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' special-use domain names ''' # http://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml import re _regexps = [ # RFC 1035, §3.5 : '.+[.]in-addr[.]arpa', # RFC 3596, §2.5 : '.+[.]ip6[.]arpa', # RFC 6761, §6 : '(.+[.])?test', '(.+[.])?localhost', '(.+[.])?invalid', '(.+[.])?example([.](com|net|org))?', # RFC 6762, §3 : '(.+[.])local', ] _is_special = re.compile( '^({re})$'.format(re='|'.join(_regexps)) ).match def is_special_domain(domain): domain = domain.lower() return _is_special(domain) def is_email_in_special_domain(email): _, domain = email.rsplit('@', 1) return is_special_domain(domain) # vim:ts=4 sw=4 et i18nspector-0.13.4/lib/cli.py0000644000000000000000000001236312312562472015654 0ustar00rootroot00000000000000# Copyright © 2012, 2013, 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' command-line interface ''' import argparse import io import os import shutil import subprocess as ipc import sys import tempfile from . import checker from . import ling from . import misc from . import paths from . import tags from . import terminal __version__ = '0.13.4' def initialize_terminal(): if sys.stdout.isatty(): terminal.initialize() if sys.stdout.errors != 'strict': return sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding=sys.stdout.encoding, errors='backslashreplace', ) class Checker(checker.Checker): def tag(self, tagname, *extra): if tagname in self.options.ignore_tags: return try: tag = tags.get_tag(tagname) except KeyError: raise misc.DataIntegrityError( 'attempted to emit an unknown tag: {tag!r}'.format(tag=tagname) ) s = tag.format(self.fake_path, *extra, color=True) print(s) def check_file(filename, *, options): checker_instance = Checker(filename, options=options) checker_instance.check() def copy_options(options, **update): kwargs = vars(options) kwargs.update(update) return argparse.Namespace(**kwargs) class UnsupportedFileType(ValueError): pass def check_deb(filename, *, options): if filename.endswith('.deb'): binary = True elif filename.endswith('.dsc'): binary = False else: raise UnsupportedFileType tmpdir = tempfile.mkdtemp(prefix='i18nspector.deb.') ignore_tags = set(options.ignore_tags) ignore_tags.add('unknown-file-type') try: if binary: ipc.check_call(['dpkg-deb', '-x', filename, tmpdir]) real_root = os.path.join(tmpdir, '') else: real_root = os.path.join(tmpdir, 's', '') with open(os.devnull) as bitbucket: ipc.check_call( ['dpkg-source', '--no-copy', '--no-check', '-x', filename, real_root], stdout=bitbucket # dpkg-source would be noisy without this... ) options = copy_options(options, ignore_tags=ignore_tags, fake_root=(real_root, os.path.join(filename, '')) ) for root, dirs, files in os.walk(tmpdir): for path in files: path = os.path.join(root, path) if os.path.islink(path): continue if os.path.isfile(path): check_file(path, options=options) finally: shutil.rmtree(tmpdir) def check_all(files, *, options): for filename in files: if options.debian: try: check_deb(filename, options=options) except UnsupportedFileType: pass else: continue check_file(filename, options=options) def main(): initialize_terminal() is_like_debian = misc.OSRelease().is_like('debian') ap = argparse.ArgumentParser(description=__doc__) ap.add_argument('--version', action='version', version='%(prog)s {}'.format(__version__)) ap.add_argument('-l', '--language', metavar='', help='assume this langauge') debian_help = 'allow checking Debian packages' + (' (enabled on this system)' if is_like_debian else '') ap.add_argument('--debian', action='store_true', default=is_like_debian, help=debian_help) ap.add_argument('--traceback', action='store_true', help=argparse.SUPPRESS) ap.add_argument('files', metavar='', nargs='+') options = ap.parse_args() files = options.files del options.files paths.check() if options.language is not None: try: language = ling.parse_language(options.language) language.fix_codes() except ling.LanguageError: if options.traceback: raise ap.error('invalid language') language.remove_encoding() language.remove_nonlinguistic_modifier() options.language = language options.ignore_tags = set() options.fake_root = None Checker.patch_environment() check_all(files, options=options) __all__ = ['main'] # vim:ts=4 sw=4 et i18nspector-0.13.4/lib/checker.py0000644000000000000000000012140512312562472016507 0ustar00rootroot00000000000000# Copyright © 2012, 2013, 2014 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' checks ''' import abc import collections import difflib import email.utils import os import re import struct import urllib.parse import polib from . import encodings as encinfo from . import gettext from . import ling from . import misc from . import polib4us from . import domains from . import tags class EnvironmentNotPatched(RuntimeError): pass class EnvironmentAlreadyPatched(RuntimeError): pass find_unusual_characters = re.compile( r'[\x00-\x08\x0B-\x1A\x1C-\x1F]' # C0 except TAB, LF, ESC r'|\x1B(?!\[)' # ESC, except when followed by [ r'|\x7F' # DEL r'|[\x80-\x9F]' # C1 '|\uFEFF' # ZERO WIDTH NO-BREAK SPACE '|\uFFFD' # REPLACEMENT CHARACTER '|[\uFFFE\uFFFF]' # non-characters r'|(?<=\w)\xBF' # INVERTED QUESTION MARK but only directly after a letter ).findall header_fields_with_dedicated_checks = set() def checks_header_fields(*fields): def identity(x): return x header_fields_with_dedicated_checks.update(fields) return identity class Checker(object, metaclass=abc.ABCMeta): _patched_environment = None @classmethod def patch_environment(cls): if cls._patched_environment is not None: raise EnvironmentAlreadyPatched encinfo.install_extra_encodings() polib4us.install_patches() cls._patched_environment = True def __init__(self, path, *, options): if self._patched_environment is not True: raise EnvironmentNotPatched self.path = path self.fake_path = path if options.fake_root is not None: (real_root, fake_root) = options.fake_root if not real_root.endswith(os.sep): raise ValueError if not fake_root.endswith(os.sep): raise ValueError if path.startswith(real_root): self.fake_path = fake_root + path[len(real_root):] self.options = options @abc.abstractmethod def tag(self, tagname, *extra): return def check(self): # If a file passed to polib doesn't exist, it will “helpfully” treat it # as PO/MO file _contents_. This is definitely not what we want. To # prevent such disaster, fail early if the file doesn't exit. try: os.stat(self.path) except EnvironmentError as exc: self.tag('os-error', tags.safestr(exc.strerror)) return extension = os.path.splitext(self.path)[-1] is_template = False if extension == '.po': constructor = polib.pofile elif extension == '.pot': constructor = polib.pofile is_template = True elif extension in ('.mo', '.gmo'): constructor = polib.mofile else: self.tag('unknown-file-type') return broken_encoding = False try: try: file = constructor(self.path) except UnicodeDecodeError as exc: broken_encoding = exc file = constructor(self.path, encoding='ISO-8859-1') except polib4us.moparser.SyntaxError as exc: self.tag('invalid-mo-file', tags.safestr(exc)) return except struct.error: self.tag('invalid-mo-file') return except IOError as exc: message = str(exc) if exc.errno is not None: self.tag('os-error', tags.safestr(exc.strerror)) return elif message.startswith('Invalid mo '): self.tag('invalid-mo-file') return elif message.startswith('Syntax error in po file '): message = message[24:] message_parts = [] if message.startswith(self.path + ' '): message = message[len(self.path)+1:] match = re.match(r'^\(line ([0-9]+)\)(?:: (.+))?$', message) if match is not None: lineno_part = 'line {}'.format(match.group(1)) message = match.group(2) if message is not None: lineno_part += ':' if re.match(r'^[a-z]+( [a-z]+)*$', message): message = tags.safestr(message) message_parts += [tags.safestr(lineno_part)] if message is not None: message_parts += [message] self.tag('syntax-error-in-po-file', *message_parts) return raise finally: if broken_encoding: s = broken_encoding.object assert isinstance(s, bytes) begin = max(broken_encoding.start - 40, 0) end = broken_encoding.start + 40 s = s[begin:end] self.tag('broken-encoding', s, tags.safestr('cannot be decoded as'), broken_encoding.encoding.upper(), ) broken_encoding = True # check_headers() modifies the file metadata, # so it has to be the first check: self.check_headers(file, is_template=is_template) language = self.check_language(file, is_template=is_template) self.check_plurals(file, is_template=is_template, language=language) encoding = self.check_mime(file, is_template=is_template, language=language) if broken_encoding: encoding = None self.check_dates(file, is_template=is_template) self.check_project(file) self.check_translator(file, is_template=is_template) self.check_messages(file, encoding=encoding) @checks_header_fields('Language', 'X-Poedit-Language', 'X-Poedit-Country') def check_language(self, file, *, is_template): duplicate_meta_language = False meta_languages = file.metadata['Language'] if len(meta_languages) > 1: self.tag('duplicate-header-field-language') meta_languages = sorted(set(meta_languages)) if len(meta_languages) > 1: duplicate_meta_language = True if len(meta_languages) == 1: [meta_language] = meta_languages else: meta_language = None orig_meta_language = meta_language if is_template: if meta_language is None: self.tag('no-language-header-field') return language = self.options.language language_source = 'command-line' language_source_quality = 1 if language is None: path_components = os.path.normpath(self.path).split('/') try: i = path_components.index('LC_MESSAGES') except ValueError: i = 0 if i > 0: language = path_components[i - 1] try: language = ling.parse_language(language) language.fix_codes() language.remove_encoding() language.remove_nonlinguistic_modifier() except ling.LanguageError: # It's not our job to report possible errors in _pathnames_. language = None else: language_source = 'pathname' del path_components, i if language is None and self.path.endswith('.po'): language, ext = os.path.splitext(os.path.basename(self.path)) assert ext == '.po' try: language = ling.parse_language(language) if language.encoding is not None: # It's very likely that something else has been confused # for the apparent encoding. raise ling.LanguageError language.fix_codes() language.remove_nonlinguistic_modifier() except ling.LanguageError: # It's not our job to report possible errors in _pathnames_. language = None else: language_source = 'pathname' language_source_quality = 0 if meta_language: try: meta_language = ling.parse_language(meta_language) except ling.LanguageError: try: new_meta_language = ling.get_language_for_name(meta_language) except LookupError: new_meta_language = None if new_meta_language: self.tag('invalid-language', orig_meta_language, '=>', new_meta_language) else: self.tag('invalid-language', orig_meta_language) meta_language = new_meta_language if meta_language: if meta_language.remove_encoding(): self.tag('encoding-in-language-header-field', orig_meta_language) if meta_language.remove_nonlinguistic_modifier(): self.tag('language-variant-does-not-affect-translation', orig_meta_language) try: if meta_language.fix_codes(): self.tag('invalid-language', orig_meta_language, '=>', meta_language) except ling.LanguageError: self.tag('invalid-language', orig_meta_language) meta_language = None if language_source_quality <= 0 and ( '/{lang}/'.format(lang=meta_language) in self.path or '/{lang}/'.format(lang=str(meta_language).replace('_', '-')) in self.path ): # For LibreOffice, PO basename does not designate translation # language, but one of the path components does. # For example, # translations/source/da/dictionaries/pl_PL.po # is a Danish translation. language = None if meta_language: if language is None: language = meta_language language_source = 'Language header field' elif language != meta_language: self.tag('language-disparity', language, tags.safestr('({})'.format(language_source)), '!=', meta_language, tags.safestr('(Language header field)') ) poedit_languages = file.metadata['X-Poedit-Language'] if len(poedit_languages) > 1: self.tag('duplicate-header-field-x-poedit', 'X-Poedit-Language') poedit_languages = sorted(set(poedit_languages)) poedit_countries = file.metadata['X-Poedit-Country'] if len(poedit_countries) > 1: self.tag('duplicate-header-field-x-poedit', 'X-Poedit-Country') poedit_countries = sorted(set(poedit_countries)) if len(poedit_languages) == 1 and len(poedit_countries) <= 1: [poedit_language] = poedit_languages # FIXME: This should take also X-Poedit-Country into account. try: poedit_language = ling.get_language_for_name(poedit_language) except LookupError: self.tag('unknown-poedit-language', poedit_language) else: if language is None: language = poedit_language language_source = 'X-Poedit-Language header field' elif language.language_code != poedit_language.language_code: self.tag('language-disparity', language, tags.safestr('({})'.format(language_source)), '!=', poedit_language, tags.safestr('(X-Poedit-Language header field)') ) if language is None: if not orig_meta_language and not duplicate_meta_language: self.tag('no-language-header-field') self.tag('unable-to-determine-language') return if not orig_meta_language and not duplicate_meta_language: self.tag('no-language-header-field', tags.safestr('Language:'), language) return language @checks_header_fields('Plural-Forms') def check_plurals(self, file, *, is_template, language): plural_forms = file.metadata['Plural-Forms'] if len(plural_forms) > 1: self.tag('duplicate-header-field-plural-forms') plural_forms = sorted(set(plural_forms)) if len(plural_forms) > 1: return if len(plural_forms) == 1: [plural_forms] = plural_forms else: assert len(plural_forms) == 0 plural_forms = None correct_plural_forms = None if language is not None: correct_plural_forms = language.get_plural_forms() has_plurals = False # messages with plural forms (translated or not)? expected_nplurals = {} # number of plurals in _translated_ messages for message in file: if message.obsolete: continue if message.msgid_plural: has_plurals = True if not message.translated(): continue expected_nplurals[len(message.msgstr_plural)] = message if len(expected_nplurals) > 1: break if len(expected_nplurals) > 1: args = [] for n, message in sorted(expected_nplurals.items()): args += [n, message_repr(message, template='({})'), '!='] self.tag('inconsistent-number-of-plural-forms', *args[:-1]) if is_template: plural_forms_hint = 'nplurals=INTEGER; plural=EXPRESSION;' elif correct_plural_forms: plural_forms_hint = tags.safe_format( ' or '.join('{}' for s in correct_plural_forms), *correct_plural_forms ) else: plural_forms_hint = 'nplurals=; plural=' if plural_forms is None: if has_plurals: if expected_nplurals: self.tag('no-required-plural-forms-header-field', plural_forms_hint) else: self.tag('no-plural-forms-header-field', plural_forms_hint) return if is_template: return try: (n, expr) = gettext.parse_plural_forms(plural_forms) except gettext.PluralFormsSyntaxError: if has_plurals: self.tag('syntax-error-in-plural-forms', plural_forms, '=>', plural_forms_hint) else: self.tag('syntax-error-in-unused-plural-forms', plural_forms, '=>', plural_forms_hint) else: if len(expected_nplurals) == 1: [expected_nplurals] = expected_nplurals.keys() if n != expected_nplurals: self.tag('incorrect-number-of-plural-forms', n, tags.safestr('(Plural-Forms header field)'), '!=', expected_nplurals, tags.safestr('(number of msgstr items)') ) locally_correct_n = locally_correct_expr = None if correct_plural_forms is not None: locally_correct_plural_forms = [ (i, expression) for i, expression in map(gettext.parse_plural_forms, correct_plural_forms) if i == n ] if not locally_correct_plural_forms: if has_plurals: self.tag('incorrect-plural-forms', plural_forms, '=>', plural_forms_hint) else: self.tag('incorrect-unused-plural-forms', plural_forms, '=>', plural_forms_hint) elif len(locally_correct_plural_forms) == 1: [[locally_correct_n, locally_correct_expr]] = locally_correct_plural_forms try: for i in range(200): fi = expr(i) if fi >= n: message = tags.safe_format('f({}) = {} >= {}'.format(i, fi, n)) if has_plurals: self.tag('codomain-error-in-plural-forms', message) else: self.tag('codomain-error-in-unused-plural-forms', message) break if n == locally_correct_n and fi != locally_correct_expr(i): if has_plurals: self.tag('incorrect-plural-forms', plural_forms, '=>', plural_forms_hint) else: self.tag('incorrect-unused-plural-forms', plural_forms, '=>', plural_forms_hint) break except OverflowError: message = tags.safe_format('f({}): integer overflow', i) if has_plurals: self.tag('arithmetic-error-in-plural-forms', message) else: self.tag('arithmetic-error-in-unused-plural-forms', message) except ZeroDivisionError: message = tags.safe_format('f({}): division by zero', i) if has_plurals: self.tag('arithmetic-error-in-plural-forms', message) else: self.tag('arithmetic-error-in-unused-plural-forms', message) codomain = expr.codomain() if codomain is not None: (x, y) = codomain if x > 0: rng = range(0, x) rng = misc.format_range(rng, max=5) message = tags.safestr('f(x) != {}'.format(rng)) if has_plurals: self.tag('codomain-error-in-plural-forms', message) else: self.tag('codomain-error-in-unused-plural-forms', message) if y + 1 < n: rng = range(y + 1, n) rng = misc.format_range(rng, max=5) message = tags.safestr('f(x) != {}'.format(rng)) if has_plurals: self.tag('codomain-error-in-plural-forms', message) else: self.tag('codomain-error-in-unused-plural-forms', message) @checks_header_fields('MIME-Version', 'Content-Transfer-Encoding', 'Content-Type') def check_mime(self, file, *, is_template, language): # MIME-Version: mime_versions = file.metadata['MIME-Version'] if len(mime_versions) > 1: self.tag('duplicate-header-field-mime-version') mime_versions = sorted(set(mime_versions)) for mime_version in mime_versions: if mime_version != '1.0': self.tag('invalid-mime-version', mime_version, '=>', '1.0') if len(mime_versions) == 0: self.tag('no-mime-version-header-field', tags.safestr('MIME-Version: 1.0')) # Content-Transfer-Encoding: ctes = file.metadata['Content-Transfer-Encoding'] if len(ctes) > 1: self.tag('duplicate-header-field-content-transfer-encoding') ctes = sorted(set(ctes)) for cte in ctes: if cte != '8bit': self.tag('invalid-content-transfer-encoding', cte, '=>', '8bit') if len(ctes) == 0: self.tag('no-content-transfer-encoding-header-field', tags.safestr('Content-Transfer-Encoding: 8bit')) # Content-Type: cts = file.metadata['Content-Type'] if len(cts) > 1: self.tag('duplicate-header-field-content-type') cts = sorted(set(cts)) elif len(cts) == 0: content_type_hint = 'text/plain; charset=' self.tag('no-content-type-header-field', tags.safestr('Content-Type: ' + content_type_hint)) return encodings = set() for ct in cts: content_type_hint = 'text/plain; charset=' match = re.search(r'(\Atext/plain; )?\bcharset=([^\s;]+)\Z', ct) if match: encoding = match.group(2) try: is_ascii_compatible = encinfo.is_ascii_compatible_encoding(encoding, missing_ok=False) except encinfo.EncodingLookupError: if encoding == 'CHARSET': if not is_template: self.tag('boilerplate-in-content-type', ct) else: self.tag('unknown-encoding', encoding) encoding = None else: if not is_ascii_compatible: self.tag('non-ascii-compatible-encoding', encoding) elif encinfo.is_portable_encoding(encoding): pass else: new_encoding = encinfo.propose_portable_encoding(encoding) if new_encoding is not None: self.tag('non-portable-encoding', encoding, '=>', new_encoding) encoding = new_encoding else: self.tag('non-portable-encoding', encoding) if language is not None: unrepresentable_characters = language.get_unrepresentable_characters(encoding) if unrepresentable_characters: if len(unrepresentable_characters) > 5: unrepresentable_characters[4:] = ['...'] self.tag('unrepresentable-characters', encoding, *unrepresentable_characters) if match.group(1) is None: if encoding is not None: content_type_hint = content_type_hint.replace('', encoding) self.tag('invalid-content-type', ct, '=>', content_type_hint) if encoding is not None: encodings.add(encoding) else: self.tag('invalid-content-type', ct, '=>', content_type_hint) if len(encodings) == 1: [encoding] = encodings return encoding @checks_header_fields('POT-Creation-Date', 'PO-Revision-Date') def check_dates(self, file, *, is_template): try: content_type = file.metadata['Content-Type'][0] except IndexError: content_type = '' is_publican = content_type.startswith('application/x-publican;') for field in 'POT-Creation-Date', 'PO-Revision-Date': dates = file.metadata[field] if len(dates) > 1: self.tag('duplicate-header-field-date', field) dates = sorted(set(dates)) elif len(dates) == 0: self.tag('no-date-header-field', field) continue for date in dates: if is_template and field.startswith('PO-') and (date == gettext.boilerplate_date): continue if 'T' in date and is_publican: # Publican uses DateTime->now(), which uses the UTC timezone by default: # http://sources.debian.net/src/publican/2.8-3/lib/Publican/Translate.pm?hl=748#L744 # http://bugs.debian.org/714739 tz_hint = '+0000' else: tz_hint = None try: fixed_date = gettext.fix_date_format(date, tz_hint=tz_hint) except gettext.BoilerplateDate: self.tag('boilerplate-in-date', tags.safestr(field + ':'), date) continue except gettext.DateSyntaxError: self.tag('invalid-date', tags.safestr(field + ':'), date) continue else: if date != fixed_date: self.tag('invalid-date', tags.safestr(field + ':'), date, '=>', fixed_date) stamp = gettext.parse_date(fixed_date) if stamp > misc.utc_now(): self.tag('date-from-future', tags.safestr(field + ':'), date) if stamp < gettext.epoch: self.tag('ancient-date', tags.safestr(field + ':'), date) @checks_header_fields('Project-Id-Version', 'Report-Msgid-Bugs-To') def check_project(self, file): # Project-Id-Version: project_id_versions = file.metadata['Project-Id-Version'] if len(project_id_versions) > 1: self.tag('duplicate-header-field-project-id-version') project_id_versions = sorted(set(project_id_versions)) elif len(project_id_versions) == 0: self.tag('no-project-id-version-header-field') for project_id_version in project_id_versions: if project_id_version in {'PACKAGE VERSION', 'PROJECT VERSION'}: self.tag('boilerplate-in-project-id-version', project_id_version) else: if not re.compile(r'[^_\d\W]', re.UNICODE).search(project_id_version): self.tag('no-package-name-in-project-id-version', project_id_version) if not re.search(r'[0-9]', project_id_version): self.tag('no-version-in-project-id-version', project_id_version) # Report-Msgid-Bugs-To: report_msgid_bugs_tos = file.metadata['Report-Msgid-Bugs-To'] if len(report_msgid_bugs_tos) > 1: self.tag('duplicate-header-field-report-msgid-bugs-to') report_msgid_bugs_tos = sorted(set(report_msgid_bugs_tos)) if report_msgid_bugs_tos == ['']: report_msgid_bugs_tos = [] if len(report_msgid_bugs_tos) == 0: self.tag('no-report-msgid-bugs-to-header-field') for report_msgid_bugs_to in report_msgid_bugs_tos: real_name, email_address = email.utils.parseaddr(report_msgid_bugs_to) if '@' not in email_address: uri = urllib.parse.urlparse(report_msgid_bugs_to) if uri.scheme == '': self.tag('invalid-report-msgid-bugs-to', report_msgid_bugs_to) elif domains.is_email_in_special_domain(email_address): self.tag('invalid-report-msgid-bugs-to', report_msgid_bugs_to) elif email_address == 'EMAIL@ADDRESS': self.tag('boilerplate-in-report-msgid-bugs-to', report_msgid_bugs_to) @checks_header_fields('Last-Translator', 'Language-Team') def check_translator(self, file, *, is_template): # Last-Translator: translators = file.metadata['Last-Translator'] if len(translators) > 1: self.tag('duplicate-header-field-last-translator') translators = sorted(set(translators)) elif len(translators) == 0: self.tag('no-last-translator-header-field') translator_emails = set() for translator in translators: translator_name, translator_email = email.utils.parseaddr(translator) translator_emails.add(translator_email) if '@' not in translator_email: self.tag('invalid-last-translator', translator) elif domains.is_email_in_special_domain(translator_email): self.tag('invalid-last-translator', translator) elif translator_email == 'EMAIL@ADDRESS': if not is_template: self.tag('boilerplate-in-last-translator', translator) # Language-Team: teams = file.metadata['Language-Team'] if len(teams) > 1: self.tag('duplicate-header-field-language-team') teams = sorted(set(teams)) elif len(teams) == 0: self.tag('no-language-team-header-field') for team in teams: team_name, team_email = email.utils.parseaddr(team) if '@' not in team_email: # TODO: An URL is also allowed here. # self.tag('invalid-language-team', translator) pass elif domains.is_email_in_special_domain(team_email): self.tag('invalid-language-team', team) elif team_email in {'LL@li.org', 'EMAIL@ADDRESS'}: if not is_template: self.tag('boilerplate-in-language-team', team) else: if team_email in translator_emails: self.tag('language-team-equal-to-last-translator', team, translator) def check_headers(self, file, *, is_template): metadata = collections.defaultdict(list) strays = [] file.header_entry = None seen_header_entry = False for entry in file: if not is_header_entry(entry) or entry.obsolete: continue if seen_header_entry: self.tag('duplicate-header-entry') break if entry.occurrences: self.tag('empty-msgid-message-with-source-code-references', *(':'.join((path, line)) for path, line in entry.occurrences) ) if entry.msgid_plural or entry.msgstr_plural: self.tag('empty-msgid-message-with-plural-forms') try: msgstr = entry.msgstr_plural['0'] # https://bitbucket.org/izi/polib/issue/49 except LookupError: msgstr = entry.msgstr_plural.get(0, entry.msgstr) for line in gettext.parse_header(msgstr): if isinstance(line, dict): [(key, value)] = line.items() metadata[key] += [value] else: strays += [line] flags = collections.Counter(resplit_flags(entry.flags)) for flag, n in sorted(flags.items()): if flag == 'fuzzy': if not is_template: self.tag('fuzzy-header-entry') elif difflib.get_close_matches(flag.lower(), ['fuzzy'], cutoff=0.8): self.tag('unexpected-flag-for-header-entry', flag, '=>', 'fuzzy') else: self.tag('unexpected-flag-for-header-entry', flag) if n > 1: self.tag('duplicate-flag-for-header-entry', flag) if entry is not file[0]: self.tag('distant-header-entry') unusual_chars = set(find_unusual_characters(msgstr)) if unusual_chars: unusual_char_names = ', '.join( 'U+{:04X} {}'.format(ord(ch), encinfo.get_character_name(ch)) for ch in sorted(unusual_chars) ) self.tag('unusual-character-in-header-entry', tags.safestr(unusual_char_names)) seen_header_entry = True seen_conflict_marker = False for stray in strays: if gettext.search_for_conflict_marker(stray): if not seen_conflict_marker: self.tag('conflict-marker-in-header-entry', stray) seen_conflict_marker = True else: self.tag('stray-header-line', stray) header_fields = frozenset(gettext.header_fields) header_fields_lc = {str.lower(s): s for s in header_fields} for key, values in sorted(metadata.items()): if not key.startswith('X-'): if key not in header_fields: hint = header_fields_lc.get(key.lower()) if hint is None: hints = difflib.get_close_matches(key, header_fields, n=1, cutoff=0.8) if hints: [hint] = hints if hint in metadata: hint = None if hint is None: self.tag('unknown-header-field', key) else: self.tag('unknown-header-field', key, '=>', hint) if len(values) > 1 and key not in header_fields_with_dedicated_checks: self.tag('duplicate-header-field', key) file.metadata = metadata del file.metadata_is_fuzzy def check_messages(self, file, *, encoding): if encoding is None: return found_unusual_characters = set() msgid_counter = collections.Counter() messages = [msg for msg in file if not is_header_entry(msg)] for message in messages: if message.obsolete: continue if is_header_entry(message): continue flags = collections.Counter(resplit_flags(message.flags)) fuzzy = False wrap = None format_flags = collections.defaultdict(dict) for flag, n in sorted(flags.items()): known_flag = True if flag == 'fuzzy': fuzzy = True elif flag in {'wrap', 'no-wrap'}: new_wrap = flag == 'wrap' if wrap == (not new_wrap): self.tag('conflicting-message-flags', message_repr(message, template='{}:'), 'wrap', 'no-wrap' ) else: wrap = new_wrap elif flag.startswith('range:'): if not message.msgid_plural: self.tag('range-flag-without-plural-string') match = re.match('([0-9]+)[.][.]([0-9]+)', flag[6:].strip(' \t\r\f\v')) if match is not None: i, j = map(int, match.groups()) if i >= j: match = None if match is None: self.tag('invalid-range-flag', message_repr(message, template='{}:'), flag ) elif flag.endswith('-format'): known_flag = False for prefix in 'no-', 'possible-', 'impossible-', '': tp = prefix.rstrip('-') if not flag.startswith(prefix): continue string_format = flag[len(prefix):-7] if string_format in gettext.string_formats: known_flag = True format_flags[tp][string_format] = flag break else: known_flag = False if not known_flag: self.tag('unknown-message-flag', message_repr(message, template='{}:'), flag ) if n > 1 and flag: self.tag('duplicate-message-flag', message_repr(message, template='{}:'), flag ) positive_format_flags = format_flags[''] if len(positive_format_flags) > 1: self.tag('conflicting-message-flags', message_repr(message, template='{}:'), *sorted(positive_format_flags.values()) ) elif len(positive_format_flags) == 1: [[positive_format, positive_format_flag]] = positive_format_flags.items() negative_format_flags = sorted( format_flag for fmt, format_flag in format_flags['no'].items() if fmt != positive_format ) if negative_format_flags: args = ( negative_format_flags + [tags.safe_format('(implied by {flag})'.format(flag=positive_format_flag))] ) self.tag('redundant-message-flag', message_repr(message, template='{}:'), *args ) for positive_key, negative_key in [('', 'no'), ('', 'impossible'), ('possible', 'impossible')]: positive_format_flags = format_flags[positive_key] negative_format_flags = format_flags[negative_key] conflicting_formats = frozenset(positive_format_flags) & frozenset(negative_format_flags) for fmt in sorted(conflicting_formats): self.tag('conflicting-message-flags', message_repr(message, template='{}:'), positive_format_flags[fmt], negative_format_flags[fmt], ) positive_format_flags = format_flags[''] possible_format_flags = format_flags['possible'] redundant_formats = frozenset(positive_format_flags) & frozenset(possible_format_flags) for fmt in sorted(redundant_formats): self.tag('redundant-message-flag', message_repr(message, template='{}:'), possible_format_flags[fmt], tags.safe_format('(implied by {flag})'.format(flag=positive_format_flags[fmt])) ) leading_lf = message.msgid.startswith('\n') trailing_lf = message.msgid.endswith('\n') strings = [message.msgid_plural] if not fuzzy: strings += [message.msgstr] strings += message.msgstr_plural.values() strings = [s for s in strings if s != ''] for s in strings: if s.startswith('\n') != leading_lf: self.tag('inconsistent-leading-newlines', message_repr(message)) break for s in strings: if s.endswith('\n') != trailing_lf: self.tag('inconsistent-trailing-newlines', message_repr(message)) break msgid_uc = ( set(find_unusual_characters(message.msgid)) | set(find_unusual_characters(message.msgid_plural)) ) strings = [message.msgstr] + sorted(message.msgstr_plural.values()) conflict_marker = None for msgstr in strings: msgstr_uc = set(find_unusual_characters(msgstr)) uc = msgstr_uc - msgid_uc - found_unusual_characters if uc: names = ', '.join( 'U+{:04X} {}'.format(ord(ch), encinfo.get_character_name(ch)) for ch in sorted(uc) ) self.tag('unusual-character-in-translation', tags.safestr(names + ':'), msgstr) found_unusual_characters |= uc if conflict_marker is None: conflict_marker = gettext.search_for_conflict_marker(msgstr) if conflict_marker is not None: conflict_marker = conflict_marker.group(0) self.tag('conflict-marker-in-translation', message_repr(message), conflict_marker) msgid_counter[message.msgid, message.msgctxt] += 1 if msgid_counter[message.msgid, message.msgctxt] == 2: self.tag('duplicate-message-definition', message_repr(message)) if len(msgid_counter) == 0: possible_hidden_strings = False if isinstance(file, polib.MOFile): possible_hidden_strings = file.possible_hidden_strings if not possible_hidden_strings: self.tag('empty-file') __all__ = ['Checker'] def is_header_entry(entry): return ( entry.msgid == '' and entry.msgctxt is None ) def resplit_flags(flags): return ( flag.strip(' \t\r\f\v') for subflags in flags for flag in subflags.split(',') ) # work-around for https://bitbucket.org/izi/polib/issue/46 def message_repr(message, template='{}'): subtemplate = 'msgid {id}' kwargs = dict(id=message.msgid) if message.msgctxt is not None: subtemplate += ' msgctxt {ctxt}' kwargs.update(ctxt=message.msgctxt) template = template.format(subtemplate) return tags.safe_format(template, **kwargs) # vim:ts=4 sw=4 et i18nspector-0.13.4/lib/__init__.py0000644000000000000000000000000012312562472016625 0ustar00rootroot00000000000000i18nspector-0.13.4/i18nspector0000755000000000000000000000435412312562472016073 0ustar00rootroot00000000000000#!/usr/bin/python3 # encoding=UTF-8 # Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ''' checking tool for gettext POT, PO and MO files ''' import os import sys # ---------------------------------------- def error(message): try: import argparse ap = argparse.ArgumentParser() prog = ap.prog except ImportError: import optparse ap = optparse.OptionParser() prog = ap.get_prog_name() message = ''.join((prog, ': error: ', message, '\n')) ap.exit(1, message) def require_python(*version): if sys.version_info < version: version_str = '.'.join(map(str, version)) message = 'Python >= %s is required' % version_str error(message) require_python(3, 2) # ---------------------------------------- basedir_fallback = None basedir = os.environ.get('I18NSPECTOR_BASEDIR', basedir_fallback) if basedir is None: basedir = os.path.dirname( os.path.realpath(__file__) ) basedir = os.path.join(basedir, '') os.stat(basedir) sys.path[:0] = [basedir] from lib import paths assert os.path.samefile(basedir, paths.basedir) from lib import cli cli.__doc__ = (__doc__ or '').strip() cli.main() # vim:ts=4 sw=4 et i18nspector-0.13.4/doc/0000755000000000000000000000000012312562473014526 5ustar00rootroot00000000000000i18nspector-0.13.4/doc/i18nspector.10000644000000000000000000007637612312562473017012 0ustar00rootroot00000000000000.\" Man page generated from reStructuredText. . .TH I18NSPECTOR 1 "2014-03-20" "i18nspector 0.13.4" "" .SH NAME i18nspector \- checking tool for gettext POT, PO and MO files . .nr rst2man-indent-level 0 . .de rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .SH SYNOPSIS .sp \fBi18nspector\fP [\-\-language \fI\fP] [\-\-debian] \fI\fP [\fI\fP …] .SH OPTIONS .INDENT 0.0 .TP .BI \-l \ \fP,\fB \ \-\-language \ Assume this language. \fI\fP should be a 2\- or 3\-letter ISO 639 language code, possibly followed by underscore and a 2\-letter ISO 3166 territory code. .TP .B \-\-debian Allow checking Debian (binary or source) packages. This option is enabled by default on modern Debian systems and its derivatives; it needs to be explicitly enabled on other systems. .UNINDENT .SH DESCRIPTION .sp \fBi18nspector\fP is a tool for checking translation templates (POT), message catalogues (PO) and compiled message catalogues (MO) files for common problems. These files are used by the GNU gettext translation functions and tools in many different development environments. .sp The following format is used for all the reported problems: .sp \ \ \fIcode\fP\fB:\fP \fIfile\fP\fB:\fP \fItag\fP [\fIextra\fP] .sp where: .INDENT 0.0 .IP \(bu 2 \fIcode\fP is a letter indicating type of the message: \fBE\fP (error), \fBW\fP (warning), \fBI\fP (informative message), or \fBP\fP (pedantic message); .IP \(bu 2 \fItag\fP is a name of the problem that was discovered; .IP \(bu 2 \fIextra\fP can contain additional information about the problem. .UNINDENT .SH TAGS .\" This file has been generated automatically by private/tags-as-rst. .\" Do not edit. . .SS ancient\-date .sp The date refers to the time before the first GNU gettext release. As such, it's extremely unlikely to be correct. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://git.savannah.gnu.org/cgit/gettext.git/tree/ChangeLog.0#n1767\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS arithmetic\-error\-in\-plural\-forms .sp Computing a plural form value triggers division by zero or integer overflow. This normally indicates an error in the plural form expression. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS arithmetic\-error\-in\-unused\-plural\-forms .sp Computing a plural form value triggers division by zero or integer overflow. (But there are no translated messages which use plural forms.) This normally indicates an error in the plural form expression. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, possible .UNINDENT .UNINDENT .SS boilerplate\-in\-content\-type .sp The Content\-Type header field contains xgettext boilerplate. It should be in the form \fBtext/plain; charset=\fP\fIencoding\fP\&. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, certain .UNINDENT .UNINDENT .SS boilerplate\-in\-date .sp The date header field contains xgettext boilerplate. The date format should be \fBYYYY\-MM\-DD hh:mm+ZZzz\fP, e.g. \fB2011\-11\-05 10:14+0100\fP\&. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS boilerplate\-in\-language\-team .sp The Language\-Team header field contains xgettext boilerplate. It should contain English name of the language, and the email address or homepage URL of the language team. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, certain .UNINDENT .UNINDENT .SS boilerplate\-in\-last\-translator .sp The Last\-Translator header field contains xgettext boilerplate. It should contain the last translator's name and email address. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS boilerplate\-in\-project\-id\-version .sp The Project\-Id\-Version header field contains xgettext boilerplate. It should contain the name and the version of the package. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, certain .UNINDENT .UNINDENT .SS boilerplate\-in\-report\-msgid\-bugs\-to .sp The Report\-Msgid\-Bugs\-To header field contains xgettext boilerplate. It should contain an email address or URL where one can report bugs in the untranslated strings. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS broken\-encoding .sp Header fields and messages contained by this file couldn't be decoded to Unicode. The usual cause of this is incorrect or missing encoding declaration. .sp Note that in the absence of encoding declaration, i18nspector assumes ASCII encoding. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .sp \fI\%http://tools.ietf.org/html/rfc2045#section\-5\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS codomain\-error\-in\-plural\-forms .sp Either a plural form value is outside the declared range, or some values within the declared range can never be reached. This normally indicates an error in the plural form expression. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS codomain\-error\-in\-unused\-plural\-forms .sp Either a plural form value is outside the declared range, or some values within the declared range can never be reached. (But there are no translated messages which use plural forms.) This normally indicates an error in the plural form expression. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, possible .UNINDENT .UNINDENT .SS conflict\-marker\-in\-header\-entry .sp The header contains a conflict marker (\fB#\-#\-#\-#\-#\fP \fI…\fP \fB#\-#\-#\-#\-#\fP). The conflict will have to be resolved manually. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Creating\-Compendia.html#Creating\-Compendia\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, certain .UNINDENT .UNINDENT .SS conflict\-marker\-in\-translation .sp One of the translated messages appear to contain a conflict marker (\fB#\-#\-#\-#\-#\fP \fI…\fP \fB#\-#\-#\-#\-#\fP). The conflict will have to be resolved manually. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Creating\-Compendia.html#Creating\-Compendia\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS conflicting\-message\-flags .sp Two flags with conflicting meanings are associated with one of the messages. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/PO\-Files.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, possible .UNINDENT .UNINDENT .SS date\-from\-future .sp The date refers to the future. As such, it's extremely unlikely to be correct. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS distant\-header\-entry .sp The header entry in this file is preceded by other entries. The header entry should be always the first one. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, certain .UNINDENT .UNINDENT .SS duplicate\-flag\-for\-header\-entry .sp Multiple identical flags are associated with the header entry. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, certain .UNINDENT .UNINDENT .SS duplicate\-header\-entry .sp This file contains multiple header entries. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, certain .UNINDENT .UNINDENT .SS duplicate\-header\-field .sp This file contains multiple header fields of the same name. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, wild\-guess .UNINDENT .UNINDENT .SS duplicate\-header\-field\-content\-transfer\-encoding .sp This file contains multiple Content\-Transfer\-Encoding header fields. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, certain .UNINDENT .UNINDENT .SS duplicate\-header\-field\-content\-type .sp This file contains multiple Content\-Type header fields. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, certain .UNINDENT .UNINDENT .SS duplicate\-header\-field\-date .sp This file contains multiple date header fields of the same name. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS duplicate\-header\-field\-language .sp This file contains multiple Language header fields. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, certain .UNINDENT .UNINDENT .SS duplicate\-header\-field\-language\-team .sp This file contains multiple Language\-Team header fields. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS duplicate\-header\-field\-last\-translator .sp This file contains multiple Last\-Translator header fields. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS duplicate\-header\-field\-mime\-version .sp This file contains multiple MIME\-Version header fields. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, certain .UNINDENT .UNINDENT .SS duplicate\-header\-field\-plural\-forms .sp This file contains multiple Plural\-Forms header fields. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, certain .UNINDENT .UNINDENT .SS duplicate\-header\-field\-project\-id\-version .sp This file contains multiple Project\-Id\-Version header fields. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, certain .UNINDENT .UNINDENT .SS duplicate\-header\-field\-report\-msgid\-bugs\-to .sp This file contains multiple Report\-Msgid\-Bugs\-To header fields. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS duplicate\-header\-field\-x\-poedit .sp This file contains multiple X\-Poedit\-\fI*\fP header fields. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS duplicate\-message\-definition .sp This file contains multiple definitions of the same message. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, certain .UNINDENT .UNINDENT .SS duplicate\-message\-flag .sp Multiple identical flags are associated with one of the messages. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, certain .UNINDENT .UNINDENT .SS empty\-file .sp This file doesn't contain any messages. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS empty\-msgid\-message\-with\-plural\-forms .sp The message with empty msgid contains plural forms. Such messages are reserved by GNU gettext for header entries, and your code should not call \fBngettext("", …)\fP\&. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, certain .UNINDENT .UNINDENT .SS empty\-msgid\-message\-with\-source\-code\-references .sp The message with empty msgid contains plural forms. Such messages are reserved by GNU gettext for header entries, and your code should not call \fBgettext("")\fP\&. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS encoding\-in\-language\-header\-field .sp The language header field contains encoding declaration. Such information shouldn't be included in this field. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, certain .UNINDENT .UNINDENT .SS fuzzy\-header\-entry .sp The header entry is marked as fuzzy. To increase operability with very old (<< 0.11) \fBmsgfmt\fP(1) versions, which didn't support fuzzy header entries, it shouldn't be marked as such. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://git.savannah.gnu.org/cgit/gettext.git/tree/NEWS?id=v0.11#n44\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, certain .UNINDENT .UNINDENT .SS inconsistent\-leading\-newlines .sp Some strings in an entry start with a newline, but some don't. Either all of them should start with a newline, or none of them should. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, possible .UNINDENT .UNINDENT .SS inconsistent\-number\-of\-plural\-forms .sp Number of plural forms in a message definition doesn't match number of plural forms declared in another message definition. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .sp \fI\%http://www.gnu.org/software/gettext/manual/html_node/Translating\-plural\-forms.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, certain .UNINDENT .UNINDENT .SS inconsistent\-trailing\-newlines .sp Some strings in an entry end with a newline, but some don't. Either all of them should end with a newline, or none of them should. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, possible .UNINDENT .UNINDENT .SS incorrect\-number\-of\-plural\-forms .sp Number of plural forms in a message definition doesn't match number of plural forms declared in the header. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .sp \fI\%http://www.gnu.org/software/gettext/manual/html_node/Translating\-plural\-forms.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, certain .UNINDENT .UNINDENT .SS incorrect\-plural\-forms .sp The Plural\-Forms declaration is incorrect, according to i18nspector's linguistic data. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS incorrect\-unused\-plural\-forms .sp The Plural\-Forms declaration is incorrect, according to i18nspector's linguistic data. (But there are no translated messages which use plural forms.) .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, possible .UNINDENT .UNINDENT .SS invalid\-content\-transfer\-encoding .sp Value of the Content\-Transfer\-Encoding header field is invalid. It should be \fB8bit\fP\&. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .sp \fI\%http://tools.ietf.org/html/rfc2045#section\-6.1\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, certain .UNINDENT .UNINDENT .SS invalid\-content\-type .sp Value of the Content\-Type header field should is invalid. It should be in the form \fBtext/plain; charset=\fP\fIencoding\fP\&. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .sp \fI\%http://tools.ietf.org/html/rfc2045#section\-5\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, possible .UNINDENT .UNINDENT .SS invalid\-date .sp The date is invalid or in an invalid format. The format should be \fBYYYY\-MM\-DD hh:mm+ZZzz\fP, e.g. \fB2011\-11\-05 10:14+0100\fP\&. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS invalid\-language .sp The Language header field couldn't be parsed, or it contains an unknown language. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, possible .UNINDENT .UNINDENT .SS invalid\-language\-team .sp The Language\-Team header field contains an e\-mail address that uses a reserved domain name. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://tools.ietf.org/html/rfc2606\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, possible .UNINDENT .UNINDENT .SS invalid\-last\-translator .sp The Last\-Translator header field could neither be parsed as an e\-mail, or the e\-mail address uses a reserved domain name. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .sp \fI\%http://tools.ietf.org/html/rfc2606\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, possible .UNINDENT .UNINDENT .SS invalid\-mime\-version .sp Value of the MIME\-Version header field is invalid. It should be \fB1.0\fP\&. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://tools.ietf.org/html/rfc2045#section\-4\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, certain .UNINDENT .UNINDENT .SS invalid\-mo\-file .sp This file couldn't be parsed a MO file. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, certain .UNINDENT .UNINDENT .SS invalid\-range\-flag .sp A \fBrange:\fP flag couldn't be parsed, or the designated range contained less than two numbers. The syntax is \fBrange:\fP \fImin\fP\fB\&..\fP\fImax\fP, where both values are non\-negative integers. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/PO\-Files.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, certain .UNINDENT .UNINDENT .SS invalid\-report\-msgid\-bugs\-to .sp The Report\-Msgid\-Bugs\-To header field could neither be parsed as an e\-mail nor as a URL, or the e\-mail address uses a reserved domain name. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .sp \fI\%http://tools.ietf.org/html/rfc2606\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, possible .UNINDENT .UNINDENT .SS language\-disparity .sp Language of this file has been declared in multiple places, but the declarations don't match. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, possible .UNINDENT .UNINDENT .SS language\-team\-equal\-to\-last\-translator .sp Language\-Team and Last\-Translator header fields contain the same e\-mail address. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, possible .UNINDENT .UNINDENT .SS language\-variant\-does\-not\-affect\-translation .sp The Language header field contains a variant designator that is not relevant for the message translation. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, possible .UNINDENT .UNINDENT .SS no\-content\-transfer\-encoding\-header\-field .sp The Content\-Transfer\-Encoding header field doesn't exist. It should be set to \fB8bit\fP\&. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .sp \fI\%http://tools.ietf.org/html/rfc2045#section\-6.1\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, certain .UNINDENT .UNINDENT .SS no\-content\-type\-header\-field .sp The Content\-Type header field doesn't exist. It should be set to \fBtext/plain; charset=\fP\fIencoding\fP\&. .sp Note that in the absence of encoding declaration, i18nspector assumes ASCII encoding. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .sp \fI\%http://tools.ietf.org/html/rfc2045#section\-5\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, certain .UNINDENT .UNINDENT .SS no\-date\-header\-field .sp The date header field doesn't exist. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, certain .UNINDENT .UNINDENT .SS no\-language\-header\-field .sp The Language header field doesn't exist. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, certain .UNINDENT .UNINDENT .SS no\-language\-team\-header\-field .sp The Language\-Team header field does not exist. It should contain English name of the language, and the email address or homepage URL of the language team. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, certain .UNINDENT .UNINDENT .SS no\-last\-translator\-header\-field .sp The Last\-Translator header field doesn't exist. It should contain the last translator's name and email address. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS no\-mime\-version\-header\-field .sp The MIME\-Version header field does't exist. It should be to set to \fB1.0\fP\&. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://tools.ietf.org/html/rfc2045#section\-4\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, certain .UNINDENT .UNINDENT .SS no\-package\-name\-in\-project\-id\-version .sp The Project\-Id\-Version header field doesn't appear to contain any name. It should contain both the name and the version of the package. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, possible .UNINDENT .UNINDENT .SS no\-plural\-forms\-header\-field .sp The Plural\-Forms header field does not exist, even though some of the messages use plural forms (although none of them have been translated). .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, certain .UNINDENT .UNINDENT .SS no\-project\-id\-version\-header\-field .sp The Project\-Id\-Version header field does not exist. It should contain the name and the version of the package. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, certain .UNINDENT .UNINDENT .SS no\-report\-msgid\-bugs\-to\-header\-field .sp The Report\-Msgid\-Bugs\-To header field does not exist or it is empty. It should contain an email address or URL where one can report bugs in the untranslated strings. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS no\-required\-plural\-forms\-header\-field .sp The Plural\-Forms header field does not exist, even though some of the translated messages use plural forms. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, certain .UNINDENT .UNINDENT .SS no\-version\-in\-project\-id\-version .sp The Project\-Id\-Version header field doesn't appear to contain any version. It should contain both the name and the version of the package. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, possible .UNINDENT .UNINDENT .SS non\-ascii\-compatible\-encoding .sp This file uses an encoding that is not compatible with ASCII. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, certain .UNINDENT .UNINDENT .SS non\-portable\-encoding .sp This file uses an encoding that is not widely supported by software. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, certain .UNINDENT .UNINDENT .SS os\-error .sp An input/output error or another operating system error occurred while checking this file. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, certain .UNINDENT .UNINDENT .SS range\-flag\-without\-plural\-string .sp A \fBrange:\fP flag is associated with a message that doesn't have plural string. \fBrange:\fP flags only make sense for translations involving plural forms. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/PO\-Files.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS redundant\-message\-flag .sp A flags associated with one of the messages is redundant, because it's implied by another flag. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/PO\-Files.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, certain .UNINDENT .UNINDENT .SS stray\-header\-line .sp The headers contains a line that does not belong to any header. Note that RFC\-822\-style folding of long headers is not supported. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://lists.gnu.org/archive/html/bug\-gettext/2012\-12/msg00010.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, certain .UNINDENT .UNINDENT .SS syntax\-error\-in\-plural\-forms .sp Value of the Plural\-Forms header field could not be parsed. It should be in the form \fBnplurals=\fP\fIn\fP\fB; plural=\fP\fIexpression\fP\&. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS syntax\-error\-in\-po\-file .sp This file couldn't be parsed a PO file. In some rare cases this is due to incorrect or missing encoding declaration. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/PO\-Files.html\fP .sp \fI\%http://bugs.debian.org/692283\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS syntax\-error\-in\-unused\-plural\-forms .sp Value of the Plural\-Forms header field could not be parsed. (But there are no translated messages which use plural forms.) It should be in the form \fBnplurals=\fP\fIn\fP\fB; plural=\fP\fIexpression\fP\&. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, possible .UNINDENT .UNINDENT .SS unable\-to\-determine\-language .sp i18nspector was unable to determine language of this file. Absence of this information will prevent it from performing further checks. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, wild\-guess .UNINDENT .UNINDENT .SS unexpected\-flag\-for\-header\-entry .sp An unexpected flag is associated with the header entry. The only flag that makes sense for the header entry is \fBfuzzy\fP\&. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/PO\-Files.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, possible .UNINDENT .UNINDENT .SS unknown\-encoding .sp This file declares an encoding that couldn't be recognized by i18nspector. It might be a typo. Absence of encoding information will prevent i18nspector from performing further checks. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, possible .UNINDENT .UNINDENT .SS unknown\-file\-type .sp File format of this file couldn't be recognized. It might be a bug in i18nspector. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, wild\-guess .UNINDENT .UNINDENT .SS unknown\-header\-field .sp The header field name is unknown to i18nspector. It might be a typo or a capitalization error (header field names are case\-sensitive). .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://lists.gnu.org/archive/html/bug\-gettext/2012\-12/msg00010.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, wild\-guess .UNINDENT .UNINDENT .SS unknown\-message\-flag .sp An unknown flag is associated with one of the messages. It might be a typo. .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.gnu.org/software/gettext/manual/html_node/PO\-Files.html\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, wild\-guess .UNINDENT .UNINDENT .SS unknown\-poedit\-language .sp Language declared in X\-Poedit\-Language couldn't be recognized. It might be a bug in i18nspector. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, wild\-guess .UNINDENT .UNINDENT .SS unrepresentable\-characters .sp The declared encoding cannot represent all characters commonly used in this language. This is a strong indication that the declared encoding is incorrect. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS unusual\-character\-in\-header\-entry .sp The header entry contains an unusual character. This is usually an indication of an encoding problem, such as: .INDENT 0.0 .IP \(bu 2 using ISO 2022 escape sequences, or .IP \(bu 2 using UTF\-8 despite declaring an 8\-bit encoding. .UNINDENT .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.unicode.org/faq/utf_bom.html#bom6\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, certain .UNINDENT .UNINDENT .SS unusual\-character\-in\-translation .sp One of the translated messages contains an unusual character. This is usually an indication of an encoding problem, such as: .INDENT 0.0 .IP \(bu 2 using ISO 2022 escape sequences, or .IP \(bu 2 using UTF\-8 despite declaring an 8\-bit encoding. .UNINDENT .sp References: .INDENT 0.0 .INDENT 3.5 \fI\%http://www.unicode.org/faq/utf_bom.html#bom6\fP .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, possible .UNINDENT .UNINDENT .SH SEE ALSO .sp \fBmsgfmt\fP(1), particularly the \fB\-c\fP option .\" vim:ts=3 sw=3 ft=rst . .\" Generated by docutils manpage writer. . i18nspector-0.13.4/doc/tags.txt0000644000000000000000000005716112312562473016237 0ustar00rootroot00000000000000.. This file has been generated automatically by private/tags-as-rst. Do not edit. ancient-date ~~~~~~~~~~~~ The date refers to the time before the first GNU gettext release. As such, it's extremely unlikely to be correct. References: http://git.savannah.gnu.org/cgit/gettext.git/tree/ChangeLog.0#n1767 Severity, certainty: normal, certain arithmetic-error-in-plural-forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Computing a plural form value triggers division by zero or integer overflow. This normally indicates an error in the plural form expression. References: http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: serious, possible arithmetic-error-in-unused-plural-forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Computing a plural form value triggers division by zero or integer overflow. (But there are no translated messages which use plural forms.) This normally indicates an error in the plural form expression. References: http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: normal, possible boilerplate-in-content-type ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Content-Type header field contains xgettext boilerplate. It should be in the form ``text/plain; charset=``\ *encoding*. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: important, certain boilerplate-in-date ~~~~~~~~~~~~~~~~~~~ The date header field contains xgettext boilerplate. The date format should be ``YYYY-MM-DD hh:mm+ZZzz``, e.g. ``2011-11-05 10:14+0100``. Severity, certainty: normal, certain boilerplate-in-language-team ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Language-Team header field contains xgettext boilerplate. It should contain English name of the language, and the email address or homepage URL of the language team. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: minor, certain boilerplate-in-last-translator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Last-Translator header field contains xgettext boilerplate. It should contain the last translator's name and email address. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: normal, certain boilerplate-in-project-id-version ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Project-Id-Version header field contains xgettext boilerplate. It should contain the name and the version of the package. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: minor, certain boilerplate-in-report-msgid-bugs-to ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Report-Msgid-Bugs-To header field contains xgettext boilerplate. It should contain an email address or URL where one can report bugs in the untranslated strings. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: normal, certain broken-encoding ~~~~~~~~~~~~~~~ Header fields and messages contained by this file couldn't be decoded to Unicode. The usual cause of this is incorrect or missing encoding declaration. Note that in the absence of encoding declaration, i18nspector assumes ASCII encoding. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html http://tools.ietf.org/html/rfc2045#section-5 Severity, certainty: serious, possible codomain-error-in-plural-forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Either a plural form value is outside the declared range, or some values within the declared range can never be reached. This normally indicates an error in the plural form expression. References: http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: serious, possible codomain-error-in-unused-plural-forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Either a plural form value is outside the declared range, or some values within the declared range can never be reached. (But there are no translated messages which use plural forms.) This normally indicates an error in the plural form expression. References: http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: normal, possible conflict-marker-in-header-entry ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The header contains a conflict marker (``#-#-#-#-#`` *…* ``#-#-#-#-#``). The conflict will have to be resolved manually. References: http://www.gnu.org/software/gettext/manual/html_node/Creating-Compendia.html#Creating-Compendia Severity, certainty: serious, certain conflict-marker-in-translation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ One of the translated messages appear to contain a conflict marker (``#-#-#-#-#`` *…* ``#-#-#-#-#``). The conflict will have to be resolved manually. References: http://www.gnu.org/software/gettext/manual/html_node/Creating-Compendia.html#Creating-Compendia Severity, certainty: serious, possible conflicting-message-flags ~~~~~~~~~~~~~~~~~~~~~~~~~ Two flags with conflicting meanings are associated with one of the messages. References: http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html Severity, certainty: important, possible date-from-future ~~~~~~~~~~~~~~~~ The date refers to the future. As such, it's extremely unlikely to be correct. Severity, certainty: normal, certain distant-header-entry ~~~~~~~~~~~~~~~~~~~~ The header entry in this file is preceded by other entries. The header entry should be always the first one. Severity, certainty: important, certain duplicate-flag-for-header-entry ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Multiple identical flags are associated with the header entry. Severity, certainty: minor, certain duplicate-header-entry ~~~~~~~~~~~~~~~~~~~~~~ This file contains multiple header entries. Severity, certainty: serious, certain duplicate-header-field ~~~~~~~~~~~~~~~~~~~~~~ This file contains multiple header fields of the same name. Severity, certainty: minor, wild-guess duplicate-header-field-content-transfer-encoding ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This file contains multiple Content-Transfer-Encoding header fields. Severity, certainty: pedantic, certain duplicate-header-field-content-type ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This file contains multiple Content-Type header fields. Severity, certainty: serious, certain duplicate-header-field-date ~~~~~~~~~~~~~~~~~~~~~~~~~~~ This file contains multiple date header fields of the same name. Severity, certainty: normal, certain duplicate-header-field-language ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This file contains multiple Language header fields. Severity, certainty: important, certain duplicate-header-field-language-team ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This file contains multiple Language-Team header fields. Severity, certainty: normal, certain duplicate-header-field-last-translator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This file contains multiple Last-Translator header fields. Severity, certainty: normal, certain duplicate-header-field-mime-version ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This file contains multiple MIME-Version header fields. Severity, certainty: pedantic, certain duplicate-header-field-plural-forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This file contains multiple Plural-Forms header fields. Severity, certainty: serious, certain duplicate-header-field-project-id-version ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This file contains multiple Project-Id-Version header fields. Severity, certainty: minor, certain duplicate-header-field-report-msgid-bugs-to ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This file contains multiple Report-Msgid-Bugs-To header fields. Severity, certainty: normal, certain duplicate-header-field-x-poedit ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This file contains multiple X-Poedit-*\** header fields. Severity, certainty: normal, certain duplicate-message-definition ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This file contains multiple definitions of the same message. Severity, certainty: serious, certain duplicate-message-flag ~~~~~~~~~~~~~~~~~~~~~~ Multiple identical flags are associated with one of the messages. Severity, certainty: minor, certain empty-file ~~~~~~~~~~ This file doesn't contain any messages. Severity, certainty: normal, certain empty-msgid-message-with-plural-forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The message with empty msgid contains plural forms. Such messages are reserved by GNU gettext for header entries, and your code should not call ``ngettext("", …)``. Severity, certainty: serious, certain empty-msgid-message-with-source-code-references ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The message with empty msgid contains plural forms. Such messages are reserved by GNU gettext for header entries, and your code should not call ``gettext("")``. Severity, certainty: serious, possible encoding-in-language-header-field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The language header field contains encoding declaration. Such information shouldn't be included in this field. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: minor, certain fuzzy-header-entry ~~~~~~~~~~~~~~~~~~ The header entry is marked as fuzzy. To increase operability with very old (<< 0.11) **msgfmt**\ (1) versions, which didn't support fuzzy header entries, it shouldn't be marked as such. References: http://git.savannah.gnu.org/cgit/gettext.git/tree/NEWS?id=v0.11#n44 Severity, certainty: pedantic, certain inconsistent-leading-newlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Some strings in an entry start with a newline, but some don't. Either all of them should start with a newline, or none of them should. Severity, certainty: important, possible inconsistent-number-of-plural-forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Number of plural forms in a message definition doesn't match number of plural forms declared in another message definition. References: http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html http://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html Severity, certainty: serious, certain inconsistent-trailing-newlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Some strings in an entry end with a newline, but some don't. Either all of them should end with a newline, or none of them should. Severity, certainty: important, possible incorrect-number-of-plural-forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Number of plural forms in a message definition doesn't match number of plural forms declared in the header. References: http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html http://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html Severity, certainty: serious, certain incorrect-plural-forms ~~~~~~~~~~~~~~~~~~~~~~ The Plural-Forms declaration is incorrect, according to i18nspector's linguistic data. Severity, certainty: serious, possible incorrect-unused-plural-forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Plural-Forms declaration is incorrect, according to i18nspector's linguistic data. (But there are no translated messages which use plural forms.) Severity, certainty: normal, possible invalid-content-transfer-encoding ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Value of the Content-Transfer-Encoding header field is invalid. It should be ``8bit``. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html http://tools.ietf.org/html/rfc2045#section-6.1 Severity, certainty: pedantic, certain invalid-content-type ~~~~~~~~~~~~~~~~~~~~ Value of the Content-Type header field should is invalid. It should be in the form ``text/plain; charset=``\ *encoding*. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html http://tools.ietf.org/html/rfc2045#section-5 Severity, certainty: important, possible invalid-date ~~~~~~~~~~~~ The date is invalid or in an invalid format. The format should be ``YYYY-MM-DD hh:mm+ZZzz``, e.g. ``2011-11-05 10:14+0100``. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: normal, certain invalid-language ~~~~~~~~~~~~~~~~ The Language header field couldn't be parsed, or it contains an unknown language. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: important, possible invalid-language-team ~~~~~~~~~~~~~~~~~~~~~ The Language-Team header field contains an e-mail address that uses a reserved domain name. References: http://tools.ietf.org/html/rfc2606 Severity, certainty: normal, possible invalid-last-translator ~~~~~~~~~~~~~~~~~~~~~~~ The Last-Translator header field could neither be parsed as an e-mail, or the e-mail address uses a reserved domain name. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html http://tools.ietf.org/html/rfc2606 Severity, certainty: normal, possible invalid-mime-version ~~~~~~~~~~~~~~~~~~~~ Value of the MIME-Version header field is invalid. It should be ``1.0``. References: http://tools.ietf.org/html/rfc2045#section-4 Severity, certainty: pedantic, certain invalid-mo-file ~~~~~~~~~~~~~~~ This file couldn't be parsed a MO file. Severity, certainty: serious, certain invalid-range-flag ~~~~~~~~~~~~~~~~~~ A ``range:`` flag couldn't be parsed, or the designated range contained less than two numbers. The syntax is ``range:``\ *min*\ ``..``\ *max*, where both values are non-negative integers. References: http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html Severity, certainty: important, certain invalid-report-msgid-bugs-to ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Report-Msgid-Bugs-To header field could neither be parsed as an e-mail nor as a URL, or the e-mail address uses a reserved domain name. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html http://tools.ietf.org/html/rfc2606 Severity, certainty: normal, possible language-disparity ~~~~~~~~~~~~~~~~~~ Language of this file has been declared in multiple places, but the declarations don't match. Severity, certainty: normal, possible language-team-equal-to-last-translator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Language-Team and Last-Translator header fields contain the same e-mail address. Severity, certainty: minor, possible language-variant-does-not-affect-translation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Language header field contains a variant designator that is not relevant for the message translation. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: minor, possible no-content-transfer-encoding-header-field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Content-Transfer-Encoding header field doesn't exist. It should be set to ``8bit``. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html http://tools.ietf.org/html/rfc2045#section-6.1 Severity, certainty: pedantic, certain no-content-type-header-field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Content-Type header field doesn't exist. It should be set to ``text/plain; charset=``\ *encoding*. Note that in the absence of encoding declaration, i18nspector assumes ASCII encoding. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html http://tools.ietf.org/html/rfc2045#section-5 Severity, certainty: important, certain no-date-header-field ~~~~~~~~~~~~~~~~~~~~ The date header field doesn't exist. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: minor, certain no-language-header-field ~~~~~~~~~~~~~~~~~~~~~~~~ The Language header field doesn't exist. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: pedantic, certain no-language-team-header-field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Language-Team header field does not exist. It should contain English name of the language, and the email address or homepage URL of the language team. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: pedantic, certain no-last-translator-header-field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Last-Translator header field doesn't exist. It should contain the last translator's name and email address. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: normal, certain no-mime-version-header-field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The MIME-Version header field does't exist. It should be to set to ``1.0``. References: http://tools.ietf.org/html/rfc2045#section-4 Severity, certainty: pedantic, certain no-package-name-in-project-id-version ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Project-Id-Version header field doesn't appear to contain any name. It should contain both the name and the version of the package. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: minor, possible no-plural-forms-header-field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Plural-Forms header field does not exist, even though some of the messages use plural forms (although none of them have been translated). References: http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: minor, certain no-project-id-version-header-field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Project-Id-Version header field does not exist. It should contain the name and the version of the package. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: minor, certain no-report-msgid-bugs-to-header-field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Report-Msgid-Bugs-To header field does not exist or it is empty. It should contain an email address or URL where one can report bugs in the untranslated strings. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: normal, certain no-required-plural-forms-header-field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Plural-Forms header field does not exist, even though some of the translated messages use plural forms. References: http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: serious, certain no-version-in-project-id-version ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Project-Id-Version header field doesn't appear to contain any version. It should contain both the name and the version of the package. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: pedantic, possible non-ascii-compatible-encoding ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This file uses an encoding that is not compatible with ASCII. Severity, certainty: serious, certain non-portable-encoding ~~~~~~~~~~~~~~~~~~~~~ This file uses an encoding that is not widely supported by software. References: http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: important, certain os-error ~~~~~~~~ An input/output error or another operating system error occurred while checking this file. Severity, certainty: serious, certain range-flag-without-plural-string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A ``range:`` flag is associated with a message that doesn't have plural string. ``range:`` flags only make sense for translations involving plural forms. References: http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html Severity, certainty: normal, certain redundant-message-flag ~~~~~~~~~~~~~~~~~~~~~~ A flags associated with one of the messages is redundant, because it's implied by another flag. References: http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html Severity, certainty: pedantic, certain stray-header-line ~~~~~~~~~~~~~~~~~ The headers contains a line that does not belong to any header. Note that RFC-822-style folding of long headers is not supported. References: http://lists.gnu.org/archive/html/bug-gettext/2012-12/msg00010.html Severity, certainty: important, certain syntax-error-in-plural-forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Value of the Plural-Forms header field could not be parsed. It should be in the form ``nplurals=``\ *n*\ ``; plural=``\ *expression*. References: http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: serious, possible syntax-error-in-po-file ~~~~~~~~~~~~~~~~~~~~~~~ This file couldn't be parsed a PO file. In some rare cases this is due to incorrect or missing encoding declaration. References: http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html http://bugs.debian.org/692283 Severity, certainty: serious, possible syntax-error-in-unused-plural-forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Value of the Plural-Forms header field could not be parsed. (But there are no translated messages which use plural forms.) It should be in the form ``nplurals=``\ *n*\ ``; plural=``\ *expression*. References: http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: important, possible unable-to-determine-language ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ i18nspector was unable to determine language of this file. Absence of this information will prevent it from performing further checks. Severity, certainty: normal, wild-guess unexpected-flag-for-header-entry ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ An unexpected flag is associated with the header entry. The only flag that makes sense for the header entry is ``fuzzy``. References: http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html Severity, certainty: normal, possible unknown-encoding ~~~~~~~~~~~~~~~~ This file declares an encoding that couldn't be recognized by i18nspector. It might be a typo. Absence of encoding information will prevent i18nspector from performing further checks. Severity, certainty: important, possible unknown-file-type ~~~~~~~~~~~~~~~~~ File format of this file couldn't be recognized. It might be a bug in i18nspector. Severity, certainty: normal, wild-guess unknown-header-field ~~~~~~~~~~~~~~~~~~~~ The header field name is unknown to i18nspector. It might be a typo or a capitalization error (header field names are case-sensitive). References: http://lists.gnu.org/archive/html/bug-gettext/2012-12/msg00010.html Severity, certainty: minor, wild-guess unknown-message-flag ~~~~~~~~~~~~~~~~~~~~ An unknown flag is associated with one of the messages. It might be a typo. References: http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html Severity, certainty: normal, wild-guess unknown-poedit-language ~~~~~~~~~~~~~~~~~~~~~~~ Language declared in X-Poedit-Language couldn't be recognized. It might be a bug in i18nspector. Severity, certainty: minor, wild-guess unrepresentable-characters ~~~~~~~~~~~~~~~~~~~~~~~~~~ The declared encoding cannot represent all characters commonly used in this language. This is a strong indication that the declared encoding is incorrect. Severity, certainty: serious, possible unusual-character-in-header-entry ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The header entry contains an unusual character. This is usually an indication of an encoding problem, such as: * using ISO 2022 escape sequences, or * using UTF-8 despite declaring an 8-bit encoding. References: http://www.unicode.org/faq/utf_bom.html#bom6 Severity, certainty: important, certain unusual-character-in-translation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ One of the translated messages contains an unusual character. This is usually an indication of an encoding problem, such as: * using ISO 2022 escape sequences, or * using UTF-8 despite declaring an 8-bit encoding. References: http://www.unicode.org/faq/utf_bom.html#bom6 Severity, certainty: important, possible i18nspector-0.13.4/doc/todo.txt0000644000000000000000000001144512312562472016240 0ustar00rootroot00000000000000Add more ``Plural-Forms``. Document how the current ``Plural-Forms`` were obtained. * http://translate.sourceforge.net/wiki/l10n/pluralforms * http://unicode.org/cldr/trac/browser/trunk/common/supplemental/plurals.xml Complain about incorrect locale codes: * ``al`` → ``sq`` * ``bh`` → ``bho`` | ``mai`` | ``mag`` * ``ca-XV`` → ``ca@valencia`` * ``cn`` → ``zh`` * ``cz`` → ``cs`` * ``dk`` → ``da`` * ``en_UK`` → ``en_GB`` * ``gr`` → ``el`` * ``in`` → ``id`` * ``iw`` → ``he`` * ``ji`` → ``yi`` * ``mo`` → ``ro_MD`` * ``no`` → ``nb`` * ``sh_BA`` → ``bs_BA`` * ``sh_HR`` → ``hr_HR`` * ``sh_RS`` → ``sr_RS`` * ``sr@Latn`` → ``sr@latin`` * ``sr_CS`` → ``sr`` * ``sr_SR`` → ``sr_RS`` * ``sr_YU`` → ``sr`` * ``uk_UK`` → ``uk_UA`` * ``vn`` → ``vi`` Correct locale codes in invalid format, e.g.: * ``da-DK`` → ``da_DK``: http://sources.debian.net/data/main/d/debian-handbook/6.0+20121031/da-DK/00a_preface.po * ``pt_br`` → ``pt_BR``: http://sources.debian.net/data/main/p/pam-pkcs11/0.6.8-1/po/pt_br.po * ``Pt`` → ``pt``: http://sources.debian.net/data/main/d/darcsweb/1.1-3.1/debian/po/pt.po Correct ``Language`` with both a natural language and a language code, e.g. * ``nl (Dutch)``: http://sources.debian.net/data/main/g/garcon/0.1.12-1/po/nl.po * ``Serbian (sr)``: http://sources.debian.net/data/main/a/at-spi2-atk/2.5.3-2/po/sr.po Guess language from ``Language-Team``. * http://translationproject.org/team/ Add ``characters=``\ … for more languages. Document how the current values were obtained. Fix support for ``X-Poedit-Language: (Afan) Oromo``. Fix support for ``X-Poedit-Language: Serbian (Latin)``. Document the security model. Add tests for: * Debian source packages * Debian binary packages * MO files (at least against some tags) * languages with multiple correct Plural-Forms * lib.moparser * all non-Python encodings * 0x5c byte as a part of a multibyte character: http://sources.debian.net/src/vim/2:7.3.547-7/src/po/zh_TW.po#L13 * SHIFT_JIS encoding: http://git.savannah.gnu.org/cgit/gettext.git/tree/gettext-tools/src/po-lex.c?id=v0.18.3#n179 Detect question marks in unusual places. Add support for configuration files. Once it's implemented: * Disable --debian by default. * Disable --pedantic by default. Add support for profiles: severity of a tag may depend on whether you are upstream, a translator, or a user. Add support for overrides. Add option for disabling/forcing colored output. Use `blessings `_ for colored output. Check for POT files containing translations. Run ``msgfmt --check-format`` on PO files. Reimplement the EUC-TW codec with PyICU. Check for hardcoded Language in POT files. Add option for printing tag descriptions. When emitting encoding-in-language-header-field, check if the encoding matches the one from Content-Type. Test-cases: * http://sources.debian.net/data/main/r/rhn-client-tools/1.8.9-3/po/zh_CN.GB2312.po Split no-email-address-in-last-translator from invalid-last-translator. Test-cases: * http://sources.debian.net/data/main/m/mtpaint/3.40-1/po/de.po * http://sources.debian.net/data/main/y/yaboot-installer/1.1.26/debian/po/hi.po Split missing-timezone-in-date from invalid-date. Check for non-ASCII (translated?) project id. Test-case: * http://sources.debian.net/data/main/a/alarm-clock/1.2.5-1.2/po/sr.po Split {trailing,leading}-junk-in-plural-forms from syntax-error-in-plural-forms. Test-case: * http://sources.debian.net/data/main/d/dpkg/1.16.10/po/ja.po Decide what to do with commas in Last-Translator: either accept them, or provide a better error message. Test-case: * http://sources.debian.net/data/main/i/installation-guide/20130503/po/zh_TW/using-d-i.po polib PO encoding detection is not robust enough. Test-case: xfail-header-imitation.po Add support for system-dependent messages (minor revision 1). Check for PO files that are not encoding-aware: * http://www.monkey.org/openbsd/archive2/ports/200105/msg00081.html Add support for MediaWiki Translate's ``invalid-plural`` flag. Test-case: * http://sources.debian.net/data/main/e/evolution/3.4.4-3/po/fi.po Add support for pygettext's ``docstring`` flag. Apparently some versions of ``xgettext`` incorrectly produce entries with duplicate format flags. Find out and document which versions are affected. Test-case: * http://sources.debian.net/src/recode/3.6-20/i18n/recode.pot#L324 Check .desktop files: * http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s04.html Check Shared Mime Info files: * http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html Figure out what to do with software that call ``gettext("")`` intentionally. Test-case: * http://sources.debian.net/src/evolution/3.4.4-3/shell/main.c#L579 .. vim:ft=rst i18nspector-0.13.4/doc/i18nspector.txt0000644000000000000000000000305312312562472017446 0ustar00rootroot00000000000000=========== i18nspector =========== ---------------------------------------------- checking tool for gettext POT, PO and MO files ---------------------------------------------- :manual section: 1 :version: i18nspector 0.13.4 :date: |date| Synopsis -------- **i18nspector** [--language **] [--debian] ** [** …] Options ------- -l , --language Assume this language. ** should be a 2- or 3-letter ISO 639 language code, possibly followed by underscore and a 2-letter ISO 3166 territory code. --debian Allow checking Debian (binary or source) packages. This option is enabled by default on modern Debian systems and its derivatives; it needs to be explicitly enabled on other systems. Description ----------- **i18nspector** is a tool for checking translation templates (POT), message catalogues (PO) and compiled message catalogues (MO) files for common problems. These files are used by the GNU gettext translation functions and tools in many different development environments. The following format is used for all the reported problems:   *code*\ **:** *file*\ **:** *tag* [*extra*] where: * *code* is a letter indicating type of the message: **E** (error), **W** (warning), **I** (informative message), or **P** (pedantic message); * *tag* is a name of the problem that was discovered; * *extra* can contain additional information about the problem. Tags ---- .. include:: tags.txt .. |date| date:: %Y-%m-%d See also -------- **msgfmt**\ (1), particularly the ``-c`` option .. vim:ts=3 sw=3 ft=rst i18nspector-0.13.4/doc/dependencies.txt0000644000000000000000000000054712312562472017722 0ustar00rootroot00000000000000The following software is needed to run i18nspector: * Python ≥ 3.2; * polib_, a gettext catalogs manipulation library. Additionally, the following software is needed to rebuild the manual page from source: * docutils_ ≥ 0.6. .. _polib: http://pypi.python.org/pypi/polib .. _docutils: http://docutils.sourceforge.net/ .. vim:ts=3 sw=3 ft=rst i18nspector-0.13.4/doc/changelog0000644000000000000000000004743712312562472016416 0ustar00rootroot00000000000000i18nspector (0.13.4) unstable; urgency=low * Regenerate the timezone information file using tzdata 2014a. * Recognize “8859-n” (without the “ISO-” prefix) as encoding names. * Recognize *.local, *.in-addr.arpa and *.ip6.arpa as special domain names. * Fix compatibility with polib 1.0.4. http://bugs.debian.org/742162 * Improve the test suite. -- Jakub Wilk Thu, 20 Mar 2014 13:54:53 +0100 i18nspector (0.13.3) unstable; urgency=low * Fix incorrect plural expression co-domain evaluation. * Fix incorrect precedence of the boolean not operator in plural expressions. * Forbid unary plus and unary minus in plural expressions. * Improve the test suite. -- Jakub Wilk Mon, 20 Jan 2014 20:04:22 +0100 i18nspector (0.13.2) unstable; urgency=low * Reject early encodings that are not compatible with ASCII. http://bugs.python.org/issue19619 * Improve the test suite. -- Jakub Wilk Thu, 02 Jan 2014 13:30:16 +0100 i18nspector (0.13.1) unstable; urgency=low * Fix test failures with Python 3.4. * Fix stripping delay annotations from terminfo capabilities. * Improve the test suite. -- Jakub Wilk Mon, 09 Dec 2013 09:11:05 +0100 i18nspector (0.13) unstable; urgency=low * Summary of tag changes: + Added: - conflicting-message-flags - duplicate-message-flag - invalid-range-flag - range-flag-without-plural-string - redundant-message-flag - unknown-message-flag * Check for duplicate, conflicting, redundant, or unknown message flags. * Strip leading and trailing spaces from flag lines. * Be verbose when checking for messages with empty msgid with source code references. * Reduce duplicate-flag-for-header-entry severity to minor. * Check for zero width no-break space (U+FEFF) in translations and header entries. * Improve the test suite. * Work around a trailing comment parsing bug in polib. https://bitbucket.org/izi/polib/issue/51 -- Jakub Wilk Wed, 11 Sep 2013 14:00:20 +0200 i18nspector (0.12) unstable; urgency=low * Summary of tag changes: + Added: - boilerplate-in-date [ Jakub Wilk ] * Don't emit empty-file for MO files with only system-dependent messages, or with minor revision greater than 1. * Don't emit no-package-name-in-project-id-version if the package name consists of only non-ASCII letters. * Fix parsing some atypical PO comments. * Parse more date formats. * Check for xgettext boilerplate in dates. * Strip trailing whitespace when parsing header entry. * Allow only tabs and spaces between “nplurals=…” and “plural=…”. * Remove Bihari (codes “bh”, “bih”) from the data files; it's not a single language, but a language collection. * Implement 8-bit encodings without iconv(3) or iconv(1). * Add “SEE ALSO” section to the manual page. * Improve the test suite. * Improve the makefile: + Add “clean” target. + Make it possible to use a custom install(1) implementation for “make install”. (This is useful for systems such as FreeBSD which have GNU install available under the name “ginstall”.) + Fix compatibility with find(1) implementations that require a path argument. [ Christopher Meng ] * Makefile: preserve file timestamps. -- Jakub Wilk Fri, 26 Jul 2013 14:18:37 +0200 i18nspector (0.11.1) unstable; urgency=low * Fix the MO file parser: + Detect encoding by inspecting only the first message with empty msgid. + Fix compatibility with Python 3.3. Thanks to Kyrill Detinov for the bug report. * Use the custom MO file encoding detection method rather than the provided by polib. -- Jakub Wilk Mon, 24 Jun 2013 20:28:58 +0200 i18nspector (0.11) unstable; urgency=low * Summary of tag changes: + Added: - distant-header-entry - duplicate-flag-for-header-entry - duplicate-header-entry - duplicate-header-field-x-poedit - empty-msgid-message-with-plural-forms - empty-msgid-message-with-source-code-references - unexpected-flag-for-header-entry - unusual-character-in-header-entry * Fix letter codes for tags with severity important. * Reduce severity of arithmetic-error-in-unused-plural-forms, codomain-error-in-unused-plural-forms, and incorrect-unused-plural-forms to normal. * Implement custom header parser for PO files, and custom MO file parter. (The ones in polib are inadequate for i18nspector's purposes.) * Check for duplicate header entries. * Check for unusually located header entries. * Overhaul handling of duplicates and stray lines in the header entry. + Emit duplicate-header-field-x-poedit (instead of the generic duplicate-header-field) for duplicate X-Poedit-Language and X-Poedit-Country headers fields. * Work around a flag parsing bug in polib. https://bitbucket.org/izi/polib/issue/46 * Check for duplicate and unexpected flags for header entries. * Check for unusual characters in header entries. * Check for messages with empty msgid (header entries?) with source code references or plural forms. * Fix some false-positive language-disparity when PO basename does not designate translation language. * Fix the no-report-msgid-bugs-to-header-field description. * Fix a few typos in the tag descriptions. * Improve the test suite. + Add new tests. + Use a dedicated nose plugin for blackbox tests. -- Jakub Wilk Sun, 23 Jun 2013 22:42:43 +0200 i18nspector (0.10) unstable; urgency=low * Summary of tag changes: + Added: - boilerplate-in-content-type - conflict-marker-in-header-entry - conflict-marker-in-translation - duplicate-header-field-content-transfer-encoding - duplicate-header-field-content-type - duplicate-header-field-date - duplicate-header-field-language - duplicate-header-field-language-team - duplicate-header-field-last-translator - duplicate-header-field-mime-version - duplicate-header-field-plural-forms - duplicate-header-field-project-id-version - duplicate-header-field-report-msgid-bugs-to - fuzzy-header-entry * Check for boilerplate (“charset=CHARSET”) in the Content-Type header field. * Check header field name syntax. * Overhaul duplicate header field detection. + Emit duplicate-header-field only for non-standard fields. Downgrade duplicate-header-field to minor/wild-guess. + Emit duplicate-header-field-$NAME for standard fields. + Don't trust values of standard header fields if duplicates exist. * Check for conflict markers (“#-#-#-#-# … #-#-#-#-#”). * Check for fuzzy header entries. * Fix a typo in the language-team-equal-to-last-translator description. * Post-process the manual page, so that it can be more easily translated by po4a. * If iconv(3) is available in the C standard library, use it to implement encodings that are not implemented in the Python standard library. * Don't pass -s to iconv(1); it makes GNU iconv quieten errors, and other implementations don't have this option at all. * Improve the test suite: + Add new tests. + Make exception messages raised when a subprocess fails more readable. + Make it possible to use a custom Python interpreter for “make test”. -- Jakub Wilk Sat, 15 Jun 2013 17:37:22 +0200 i18nspector (0.9.2) unstable; urgency=low * When emitting broken-encoding, don't output the whole file, but only the undecodable bytes in a small context. -- Jakub Wilk Sat, 08 Jun 2013 11:40:23 +0200 i18nspector (0.9.1) unstable; urgency=low * Brown paper bag release. * Don't complain about leading/trailing newlines in fuzzy messages. Thanks to Guillem Jover for the bug report. http://bugs.debian.org/708586 * Improve the test suite. -- Jakub Wilk Fri, 17 May 2013 15:23:30 +0200 i18nspector (0.9) unstable; urgency=low * Summary of tag changes: + Added: - inconsistent-leading-newlines - inconsistent-trailing-newlines * Check for inconsistent leading/trailing newlines in messages. * Check for unusual characters also in plural translations. * Add information about version and date to the manual page. * Fix stripping delay annotations from terminfo capabilities. -- Jakub Wilk Wed, 15 May 2013 19:37:44 +0200 i18nspector (0.8.3) unstable; urgency=low * Improve the test suite. + Skip some tests when run with (pseudo-)root privileges. Thanks to Stuart Prescott for the bug report. * Add “test” target to Makefile. Thanks to Kyrill Detinov for the bug report. * Recognize “PROJECT VERSION” as boilerplate in the Project-Id-Version header field. -- Jakub Wilk Fri, 03 May 2013 01:23:29 +0200 i18nspector (0.8.2) unstable; urgency=low * Make it possible to declare that a language has more than one correct Plural-Forms. Thanks to Guillem Jover for the bug report. * Add plural forms information for the following languages: Belarusian, Bosnian, Croatian, Hungarian, Russian, Serbian, Turkish, Ukrainian. * Improve the test suite. -- Jakub Wilk Thu, 11 Apr 2013 01:13:24 +0200 i18nspector (0.8.1) unstable; urgency=low * Improve the documentation. + Document the dependencies. Thanks to Kyrill Detinov for the bug report. + Fix a grammar mistake in the unknown-encoding description. + Update description in the “NAME” section of the manual page. + Rename the “USAGE” section of the manual page as “SYNOPSIS”. + Add “DESCRIPTION” section to the manual page. + Document that --debian is enabled on modern Debian(-like) systems. * Remove an incorrect assertion in the plural expression parser. Thanks to Fabio Pirola for the bug report. * Improve the test suite. -- Jakub Wilk Sun, 24 Feb 2013 12:24:46 +0100 i18nspector (0.8) unstable; urgency=low * Summary of tag changes: + Added: - incorrect-plural-forms - incorrect-unused-plural-forms * Add writing system information for the following languages: Burmese, Maori. * Comment out plural forms information for Hungarian and some Slavic languages: Belarusian, Bosnian, Croatian, Russian, Slovak, Serbian and Ukrainian; there is no consensus for the correct plural forms expression for them. * Check for mismatches between Plural-Forms declarations and i18nspector's linguistic data. -- Jakub Wilk Fri, 01 Feb 2013 01:32:42 +0100 i18nspector (0.7.3) unstable; urgency=low * Avoid very long lists of unrepresentable characters; output at most 5 characters at a time. * Output at most 5 items of long integer ranges. * Add writing system information for the following languages: Chinese, English with Shavian alphabet, Japanese, Korean, Malagasy, Pashto, Tagalog, Volapük. * Add plural forms information for the following languages: Frisian, Malagasy, Pashto, Tagalog, Xhosa. * Improve the test suite. -- Jakub Wilk Fri, 25 Jan 2013 01:32:28 +0100 i18nspector (0.7.2) unstable; urgency=low * Add writing system information for the following languages: Assamese, Bengali, Breton, Dzongkha, Esperanto, Galician, Gujarati, Hindi, Kannada, Khmer, Malayalam, Marathi, Nepali, Oriya, Punjabi, Sindhi, Serbian Ijekavian with Latin alphabet, Sinhala, Tajik, Tamil, Telugu, Thai, Urdu, Vietnamese, Walloon. * Update alphabet information for the following languages: Asturian, Spanish. * Add plural forms information for the following languages: Afrikaans: Albanian, Amharic, Assamese, Asturian, Basque, Bengali, Breton, Catalan, Galician, Georgian, Gujarati, Hindi, Indonesian, Interlingua, Kazakh, Khmer, Kinyarwanda, Kurdish Low German, Maithili, Malayalam, Marathi, Mongolian, Nepali, Occitan, Oriya, Persian, Punjabi, Sinhala, Tajik, Tamil, Telugu, Urdu, Uyghur. -- Jakub Wilk Fri, 18 Jan 2013 00:20:50 +0100 i18nspector (0.7.1) unstable; urgency=low * Add writing system information for: - Mongolian; - Semitic languages: Amharic, Arabic, Geez, Hebrew, Tigre, Tigrinya; - Turkic languages: Azerbaijani, Crimean Tatar, Kazakh, Kyrgyz, Tatar, Turkish, Tuvinian, Uyghur, Uzbek; - Uralic languages: Estonian, Finnish, Hungarian, Northern Sami. -- Jakub Wilk Fri, 11 Jan 2013 14:05:44 +0100 i18nspector (0.7) unstable; urgency=low * Summary of tag changes: + Added: - empty-file - invalid-language-team * Check for empty files. * Check for use of RFC 2606 reserved domain names. * Add alphabet information for: - Iranian languages: Kurdish, Ossetic, Persian; - Georgian; - Basque; - Northwest Caucasian languages: Abkhazian, Adyghe. * Handle some malformed MO files more gracefully. * Add a prefix to temporary directory names. * Make it possible to override code/data directory with an evironment variable (I18NSPECTOR_BASEDIR). * Produce a useful error message when one tries to run the script with Python < 3.2. * Improve the test suite. -- Jakub Wilk Fri, 04 Jan 2013 18:12:30 +0100 i18nspector (0.6) unstable; urgency=low * Summary of tag changes: + Added: - arithmetic-error-in-plural-forms - arithmetic-error-in-unused-plural-forms - codomain-error-in-plural-forms - codomain-error-in-unused-plural-forms * Perform more checks on Plural-Forms. * Rename the ‘po-header-fields’ data file to ‘header-fields’. * User terminfo for color terminal support, instead of hardcoded EMCA-48 sequences. * Improve the test suite. * Remove some dead code. * Use ast.literal_eval() instead of eval(). -- Jakub Wilk Sun, 16 Dec 2012 21:16:28 +0100 i18nspector (0.5) unstable; urgency=low * Summary of tag changes: + Added: - stray-header-line * If a typo or a capitalization error in a header field name is detected, suggest the correct name. * Check for header lines that do not belong to any header fields. * Refactor the environment patching code. * Optimize PO file decoding. * Improve the test suite. -- Jakub Wilk Fri, 07 Dec 2012 23:08:27 +0100 i18nspector (0.4.1) unstable; urgency=low * Rename the package. -- Jakub Wilk Sun, 02 Dec 2012 16:54:08 +0100 gettext-inspector (0.4) unstable; urgency=low * Summary of tag changes: + Added: - inconsistent-number-of-plural-forms - incorrect-number-of-plural-forms - no-plural-forms-header-field - no-required-plural-forms-header-field - syntax-error-in-unused-plural-forms * Don't unpack control file directories of Debian binary packages; they almost certainly don't contain any interesting files. * Add DEL (U+007F) to the list of control characters. * Change the way message identifiers are formatted in tag output. * Perform more checks on Plural-Forms. * Upgrade syntax-error-in-plural-forms severity to serious. * Don't crash when parsing dates with double space between date and time. * Don't allow whitespace characters other than space and tab in plural expressions. * Don't emit spurious duplicate-header-field tags on multi-line header fields. * Don't complain about issues with obsolete messages. * Don't guess language from PO file name if it appears to contain an encoding declaration, as it's very likely that something else has been confused for the apparent encoding. * Try to propose encoding for invalid-content-type. * Fix untrusted input sanitization. * Work around an escape sequence decoding bug in polib. https://bitbucket.org/izi/polib/issue/31 * Fix typos and formatting errors in the manual page. * Improve the test suite. -- Jakub Wilk Fri, 30 Nov 2012 00:08:29 +0100 gettext-inspector (0.3) unstable; urgency=low * Summary of tag changes: + Added: - duplicate-header-field - duplicate-message-definition - non-ascii-compatible-encoding + Renamed: - unusual-character-in-translation (from c0-control-characters) * Add alphabet information for: - Dutch; - Romance languages (Asturian, Catalan, Corsican, French, Italian, Occitan, Portuguese, Romanian, Spanish). * Add national varieties of English and Chinese languages to the language data file. * Add “Brazilian Portuguese” as another name for pt_BR. * Check for duplicate message definitions. * Check for duplicate header fields. * Check for encodings incompatible with ASCII. * Check for more unusual characters in translations: - C0 control characters; - replacement character (U+FFFD); - inverted question mark (U+00BF) directly after a letter. * Work around a newline decoding bug in polib. http://bugs.debian.org/692283 * Improve the test suite. -- Jakub Wilk Thu, 22 Nov 2012 23:50:05 +0100 gettext-inspector (0.2) unstable; urgency=low * Summary of tag changes: + Added: - boilerplate-in-language-team - boilerplate-in-last-translator - invalid-last-translator - language-team-equal-to-last-translator - no-language-team-header-field - no-last-translator-header-field * Add support for the following encodings: - EUC-TW - GEORGIAN-PS - KOI8-RU - KOI8-T - VISCII * Don't fail if /etc/os-release doesn't exist. * Improve the test suite. * Add alphabet information for: - Albanian; - Armenian; - Baltic languages (Latvian, Lithuanian); - Celtic languages (Irish, Scottish Gaelic, Welsh); - Greek; - Germanic languages (Danish, Faroese, Frisian, German, Icelandic, Low German, Norwegian, Swedish); - South Slavic languages (Bosnian, Bulgarian, Croatian, Macedonian, Slovenian, Serbian). * Validate the Last-Translator and Language-Team header fields. -- Jakub Wilk Fri, 16 Nov 2012 19:57:26 +0100 gettext-inspector (0.1.1) unstable; urgency=low * Improve the test suite. * Makefile: remove bogus shebang. Thanks to Paul Wise for the bug report. * Add “This file has been generated automatically by […]. Do not edit.” comments where appropriate. * Add alphabet information for East Slavic languages (Belarusian, Russian, Ukrainian). * Do not make KOI8-RU an alias for KOI8-R. They are in fact distinct encodings. -- Jakub Wilk Mon, 12 Nov 2012 16:10:21 +0100 gettext-inspector (0.1) unstable; urgency=low * Initial release. * Summary of tag changes: + Added: - ancient-date - boilerplate-in-project-id-version - boilerplate-in-report-msgid-bugs-to - broken-encoding - c1-control-characters - date-from-future - encoding-in-language-header-field - invalid-content-transfer-encoding - invalid-content-type - invalid-date - invalid-language - invalid-mime-version - invalid-mo-file - invalid-report-msgid-bugs-to - language-disparity - language-variant-does-not-affect-translation - no-content-transfer-encoding-header-field - no-content-type-header-field - no-date-header-field - no-language-header-field - no-mime-version-header-field - no-package-name-in-project-id-version - no-project-id-version-header-field - no-report-msgid-bugs-to-header-field - no-version-in-project-id-version - non-portable-encoding - os-error - syntax-error-in-plural-forms - syntax-error-in-po-file - unable-to-determine-language - unknown-encoding - unknown-file-type - unknown-header-field - unknown-poedit-language - unrepresentable-characters -- Jakub Wilk Sun, 11 Nov 2012 16:22:46 +0100 i18nspector-0.13.4/doc/Makefile0000644000000000000000000000105612312562472016167 0ustar00rootroot00000000000000export LC_ALL=C rst2man = $(or $(shell which rst2man),rst2man.py) exe = i18nspector .PHONY: all all: $(exe).1 tags.txt: ../data/tags ../private/tags-as-rst > $(@).tmp mv $(@).tmp $(@) $(exe).1: $(exe).txt tags.txt $(rst2man) --input-encoding=UTF-8:strict < $(<) > $(@).tmp sed -i -e 's/^[.]de1/.de/' $(@).tmp # work-around for http://bugs.debian.org/710678 sed -i -e "s/\([a-z]\)\\\\(aq\([a-z]\)/\1'\2/g" $(@).tmp # prefer ' to \(aq when used as an apostrophe mv $(@).tmp $(@) .PHONY: clean clean: rm -f tags.txt $(exe).1 # vim:ts=4 sw=4 noet i18nspector-0.13.4/data/0000755000000000000000000000000012312562472014671 5ustar00rootroot00000000000000i18nspector-0.13.4/data/timezones0000644000000000000000000000611212312562472016631 0ustar00rootroot00000000000000# This file has been generated automatically by private/update-timezones. # Do not edit. # Last update: 2014-03-20 [timezones] ACT = -0500 ADT = +0400 -0300 AFT = +0430 AKDT = -0800 AKST = -0900 ALMST = +0700 ALMT = +0600 AMST = +0400 +0500 -0300 AMT = +0300 +0400 -0400 ANAST = +1200 +1300 ANAT = +1100 +1200 AQTST = +0500 +0600 AQTT = +0400 +0500 ARST = -0200 -0300 ART = -0300 AST = +0300 -0400 AZOST = +0000 AZOT = -0100 AZST = +0500 AZT = +0400 BDST = +0700 BDT = +0600 BNT = +0800 BOT = -0400 BRST = -0200 BRT = -0300 BST = +0100 BTT = +0600 CAST = +1100 CAT = +0200 CCT = +0630 CDT = -0400 -0500 CEST = +0200 CET = +0100 CHADT = +1345 CHAST = +1245 CHOST = +1000 CHOT = +0800 +0900 CHUT = +1000 CKT = -1000 CLST = -0300 CLT = -0400 COT = -0500 CST = +0800 +0930 +1030 -0500 -0600 CVT = -0100 CWST = +0845 +0945 CXT = +0700 ChST = +1000 DAVT = +0500 +0700 DDUT = +1000 EASST = -0500 EAST = -0600 EAT = +0300 ECT = -0500 EDT = -0400 EEST = +0300 EET = +0200 EGST = +0000 EGT = -0100 EST = +1000 +1100 -0500 FET = +0300 FJST = +1300 FJT = +1200 FKST = -0300 FKT = -0400 FNST = -0100 FNT = -0200 GALT = -0600 GAMT = -0900 GEST = +0400 +0500 GET = +0300 +0400 GFT = -0300 GILT = +1200 GMT = +0000 GST = +0400 +1000 -0200 GYT = -0400 HADT = -0900 HAST = -1000 HKT = +0800 HOVST = +0800 HOVT = +0700 HST = -1000 ICT = +0700 IDT = +0300 IOT = +0500 +0600 IRDT = +0430 IRKST = +0900 IRKT = +0800 +0900 IRST = +0330 IST = +0100 +0200 +0530 JST = +0900 KGST = +0600 KGT = +0500 +0600 KOST = +1100 +1200 KRAST = +0800 KRAT = +0700 +0800 KST = +0900 LHST = +1030 +1100 LINT = +1400 -1000 LKT = +0600 +0630 MAGST = +1200 MAGT = +1100 +1200 MART = -0930 MAWT = +0500 +0600 MDT = -0600 MEST = +0200 MET = +0100 MHT = +1200 MIST = +1100 MMT = +0630 MOT = +0800 MPT = +1000 MSD = +0400 MSK = +0300 +0400 MST = -0700 MUST = +0500 MUT = +0400 MVT = +0500 MYT = +0800 MeST = -0800 NCST = +1200 NCT = +1100 NDT = -0230 NFT = +1130 NOVST = +0700 NOVT = +0600 +0700 NPT = +0545 NRT = +1200 NST = -0330 NUT = -1100 NZDT = +1300 NZST = +1200 OMSST = +0700 OMST = +0600 +0700 ORAST = +0500 ORAT = +0400 +0500 PDT = -0700 PET = -0500 PETST = +1200 +1300 PETT = +1100 +1200 PGT = +1000 PHOT = +1300 -1100 PHT = +0800 PKST = +0600 PKT = +0500 PMDT = -0200 PMST = -0300 PNT = -0830 PONT = +1100 PST = -0800 PWT = +0900 PYST = -0300 PYT = -0400 QYZST = +0700 QYZT = +0600 RET = +0400 ROTT = -0300 SAKST = +1100 +1200 SAKT = +1000 +1100 SAMST = +0400 +0500 SAMT = +0300 +0400 SAST = +0200 SBT = +1100 SCT = +0400 SGT = +0800 SRT = -0300 SST = -1100 SYOT = +0300 TAHT = -1000 TFT = +0500 TJT = +0500 TKT = +1300 -1100 TLT = +0900 TMT = +0500 TOST = +1400 TOT = +1300 TVT = +1200 UCT = +0000 ULAST = +0900 ULAT = +0800 UTC = +0000 UYST = -0200 UYT = -0300 UZT = +0500 VET = -0400 -0430 VLAST = +1100 VLAT = +1000 +1100 VOLST = +0400 VOLT = +0300 +0400 VOST = +0600 VUT = +1100 WAKT = +1200 WARST = -0300 WART = -0400 WAST = +0200 WAT = +0100 WEST = +0100 WET = +0000 WFT = +1200 WGST = -0200 WGT = -0300 WIB = +0700 WIT = +0900 WITA = +0800 WSDT = +1400 -1000 WST = +0800 +0900 +1300 -1100 YAKST = +1000 YAKT = +0900 +1000 YEKST = +0600 YEKT = +0500 +0600 # vim:ft=dosini i18nspector-0.13.4/data/tags0000644000000000000000000005450012312562472015556 0ustar00rootroot00000000000000[ancient-date] severity = normal certainty = certain description = The date refers to the time before the first GNU gettext release. As such, it's extremely unlikely to be correct. references = http://git.savannah.gnu.org/cgit/gettext.git/tree/ChangeLog.0#n1767 [arithmetic-error-in-plural-forms] severity = serious certainty = possible description = Computing a plural form value triggers division by zero or integer overflow. This normally indicates an error in the plural form expression. references = http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html [arithmetic-error-in-unused-plural-forms] severity = normal certainty = possible description = Computing a plural form value triggers division by zero or integer overflow. (But there are no translated messages which use plural forms.) This normally indicates an error in the plural form expression. references = http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html [boilerplate-in-content-type] severity = important certainty = certain description = The Content-Type header field contains xgettext boilerplate. It should be in the form ``text/plain; charset=``\ *encoding*. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [boilerplate-in-date] severity = normal certainty = certain description = The date header field contains xgettext boilerplate. The date format should be ``YYYY-MM-DD hh:mm+ZZzz``, e.g. ``2011-11-05 10:14+0100``. [boilerplate-in-language-team] severity = minor certainty = certain description = The Language-Team header field contains xgettext boilerplate. It should contain English name of the language, and the email address or homepage URL of the language team. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [boilerplate-in-last-translator] severity = normal certainty = certain description = The Last-Translator header field contains xgettext boilerplate. It should contain the last translator's name and email address. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [boilerplate-in-project-id-version] severity = minor certainty = certain description = The Project-Id-Version header field contains xgettext boilerplate. It should contain the name and the version of the package. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [boilerplate-in-report-msgid-bugs-to] severity = normal certainty = certain description = The Report-Msgid-Bugs-To header field contains xgettext boilerplate. It should contain an email address or URL where one can report bugs in the untranslated strings. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [broken-encoding] severity = serious certainty = possible description = Header fields and messages contained by this file couldn't be decoded to Unicode. The usual cause of this is incorrect or missing encoding declaration. . Note that in the absence of encoding declaration, i18nspector assumes ASCII encoding. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html http://tools.ietf.org/html/rfc2045#section-5 [codomain-error-in-plural-forms] severity = serious certainty = possible description = Either a plural form value is outside the declared range, or some values within the declared range can never be reached. This normally indicates an error in the plural form expression. references = http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html [codomain-error-in-unused-plural-forms] severity = normal certainty = possible description = Either a plural form value is outside the declared range, or some values within the declared range can never be reached. (But there are no translated messages which use plural forms.) This normally indicates an error in the plural form expression. references = http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html [conflict-marker-in-header-entry] severity = serious certainty = certain description = The header contains a conflict marker (``#-#-#-#-#`` *…* ``#-#-#-#-#``). The conflict will have to be resolved manually. references = http://www.gnu.org/software/gettext/manual/html_node/Creating-Compendia.html#Creating-Compendia [conflict-marker-in-translation] severity = serious certainty = possible description = One of the translated messages appear to contain a conflict marker (``#-#-#-#-#`` *…* ``#-#-#-#-#``). The conflict will have to be resolved manually. references = http://www.gnu.org/software/gettext/manual/html_node/Creating-Compendia.html#Creating-Compendia [conflicting-message-flags] severity = important certainty = possible description = Two flags with conflicting meanings are associated with one of the messages. references = http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html [date-from-future] severity = normal certainty = certain description = The date refers to the future. As such, it's extremely unlikely to be correct. [distant-header-entry] severity = important certainty = certain description = The header entry in this file is preceded by other entries. The header entry should be always the first one. [duplicate-flag-for-header-entry] severity = minor certainty = certain description = Multiple identical flags are associated with the header entry. [duplicate-header-entry] severity = serious certainty = certain description = This file contains multiple header entries. [duplicate-header-field] severity = minor certainty = wild-guess description = This file contains multiple header fields of the same name. [duplicate-header-field-content-transfer-encoding] severity = pedantic certainty = certain description = This file contains multiple Content-Transfer-Encoding header fields. [duplicate-header-field-content-type] severity = serious certainty = certain description = This file contains multiple Content-Type header fields. [duplicate-header-field-date] severity = normal certainty = certain description = This file contains multiple date header fields of the same name. [duplicate-header-field-language] severity = important certainty = certain description = This file contains multiple Language header fields. [duplicate-header-field-language-team] severity = normal certainty = certain description = This file contains multiple Language-Team header fields. [duplicate-header-field-last-translator] severity = normal certainty = certain description = This file contains multiple Last-Translator header fields. [duplicate-header-field-mime-version] severity = pedantic certainty = certain description = This file contains multiple MIME-Version header fields. [duplicate-header-field-plural-forms] severity = serious certainty = certain description = This file contains multiple Plural-Forms header fields. [duplicate-header-field-project-id-version] severity = minor certainty = certain description = This file contains multiple Project-Id-Version header fields. [duplicate-header-field-report-msgid-bugs-to] severity = normal certainty = certain description = This file contains multiple Report-Msgid-Bugs-To header fields. [duplicate-header-field-x-poedit] severity = normal certainty = certain description = This file contains multiple X-Poedit-*\** header fields. [duplicate-message-definition] severity = serious certainty = certain description = This file contains multiple definitions of the same message. [duplicate-message-flag] severity = minor certainty = certain description = Multiple identical flags are associated with one of the messages. [empty-file] severity = normal certainty = certain description = This file doesn't contain any messages. [empty-msgid-message-with-plural-forms] severity = serious certainty = certain description = The message with empty msgid contains plural forms. Such messages are reserved by GNU gettext for header entries, and your code should not call ``ngettext("", …)``. [empty-msgid-message-with-source-code-references] severity = serious certainty = possible description = The message with empty msgid contains plural forms. Such messages are reserved by GNU gettext for header entries, and your code should not call ``gettext("")``. [encoding-in-language-header-field] severity = minor certainty = certain description = The language header field contains encoding declaration. Such information shouldn't be included in this field. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [fuzzy-header-entry] severity = pedantic certainty = certain description = The header entry is marked as fuzzy. To increase operability with very old (<< 0.11) **msgfmt**\ (1) versions, which didn't support fuzzy header entries, it shouldn't be marked as such. references = http://git.savannah.gnu.org/cgit/gettext.git/tree/NEWS?id=v0.11#n44 [inconsistent-leading-newlines] severity = important certainty = possible description = Some strings in an entry start with a newline, but some don't. Either all of them should start with a newline, or none of them should. [inconsistent-number-of-plural-forms] severity = serious certainty = certain description = Number of plural forms in a message definition doesn't match number of plural forms declared in another message definition. references = http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html http://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html [inconsistent-trailing-newlines] severity = important certainty = possible description = Some strings in an entry end with a newline, but some don't. Either all of them should end with a newline, or none of them should. [incorrect-number-of-plural-forms] severity = serious certainty = certain description = Number of plural forms in a message definition doesn't match number of plural forms declared in the header. references = http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html http://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html [incorrect-plural-forms] severity = serious certainty = possible description = The Plural-Forms declaration is incorrect, according to i18nspector's linguistic data. [incorrect-unused-plural-forms] severity = normal certainty = possible description = The Plural-Forms declaration is incorrect, according to i18nspector's linguistic data. (But there are no translated messages which use plural forms.) [invalid-content-transfer-encoding] severity = pedantic certainty = certain description = Value of the Content-Transfer-Encoding header field is invalid. It should be ``8bit``. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html http://tools.ietf.org/html/rfc2045#section-6.1 [invalid-content-type] severity = important certainty = possible description = Value of the Content-Type header field should is invalid. It should be in the form ``text/plain; charset=``\ *encoding*. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html http://tools.ietf.org/html/rfc2045#section-5 [invalid-date] severity = normal certainty = certain description = The date is invalid or in an invalid format. The format should be ``YYYY-MM-DD hh:mm+ZZzz``, e.g. ``2011-11-05 10:14+0100``. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [invalid-language] severity = important certainty = possible description = The Language header field couldn't be parsed, or it contains an unknown language. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [invalid-language-team] severity = normal certainty = possible description = The Language-Team header field contains an e-mail address that uses a reserved domain name. references = http://tools.ietf.org/html/rfc2606 [invalid-last-translator] severity = normal certainty = possible description = The Last-Translator header field could neither be parsed as an e-mail, or the e-mail address uses a reserved domain name. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html http://tools.ietf.org/html/rfc2606 [invalid-mime-version] severity = pedantic certainty = certain description = Value of the MIME-Version header field is invalid. It should be ``1.0``. references = http://tools.ietf.org/html/rfc2045#section-4 [invalid-mo-file] severity = serious certainty = certain description = This file couldn't be parsed a MO file. [invalid-range-flag] severity = important certainty = certain description = A ``range:`` flag couldn't be parsed, or the designated range contained less than two numbers. The syntax is ``range:``\ *min*\ ``..``\ *max*, where both values are non-negative integers. references = http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html [invalid-report-msgid-bugs-to] severity = normal certainty = possible description = The Report-Msgid-Bugs-To header field could neither be parsed as an e-mail nor as a URL, or the e-mail address uses a reserved domain name. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html http://tools.ietf.org/html/rfc2606 [language-disparity] severity = normal certainty = possible description = Language of this file has been declared in multiple places, but the declarations don't match. [language-team-equal-to-last-translator] severity = minor certainty = possible description = Language-Team and Last-Translator header fields contain the same e-mail address. [language-variant-does-not-affect-translation] severity = minor certainty = possible description = The Language header field contains a variant designator that is not relevant for the message translation. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [no-content-transfer-encoding-header-field] severity = pedantic certainty = certain description = The Content-Transfer-Encoding header field doesn't exist. It should be set to ``8bit``. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html http://tools.ietf.org/html/rfc2045#section-6.1 [no-content-type-header-field] severity = important certainty = certain description = The Content-Type header field doesn't exist. It should be set to ``text/plain; charset=``\ *encoding*. . Note that in the absence of encoding declaration, i18nspector assumes ASCII encoding. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html http://tools.ietf.org/html/rfc2045#section-5 [no-date-header-field] severity = minor certainty = certain description = The date header field doesn't exist. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [no-language-header-field] severity = pedantic certainty = certain description = The Language header field doesn't exist. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [no-language-team-header-field] severity = pedantic certainty = certain description = The Language-Team header field does not exist. It should contain English name of the language, and the email address or homepage URL of the language team. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [no-last-translator-header-field] severity = normal certainty = certain description = The Last-Translator header field doesn't exist. It should contain the last translator's name and email address. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [no-mime-version-header-field] severity = pedantic certainty = certain description = The MIME-Version header field does't exist. It should be to set to ``1.0``. references = http://tools.ietf.org/html/rfc2045#section-4 [no-package-name-in-project-id-version] severity = minor certainty = possible description = The Project-Id-Version header field doesn't appear to contain any name. It should contain both the name and the version of the package. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [no-plural-forms-header-field] severity = minor certainty = certain description = The Plural-Forms header field does not exist, even though some of the messages use plural forms (although none of them have been translated). references = http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html [no-project-id-version-header-field] severity = minor certainty = certain description = The Project-Id-Version header field does not exist. It should contain the name and the version of the package. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [no-report-msgid-bugs-to-header-field] severity = normal certainty = certain description = The Report-Msgid-Bugs-To header field does not exist or it is empty. It should contain an email address or URL where one can report bugs in the untranslated strings. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [no-required-plural-forms-header-field] severity = serious certainty = certain description = The Plural-Forms header field does not exist, even though some of the translated messages use plural forms. references = http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html [no-version-in-project-id-version] severity = pedantic certainty = possible description = The Project-Id-Version header field doesn't appear to contain any version. It should contain both the name and the version of the package. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [non-ascii-compatible-encoding] severity = serious certainty = certain description = This file uses an encoding that is not compatible with ASCII. [non-portable-encoding] severity = important certainty = certain description = This file uses an encoding that is not widely supported by software. references = http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [os-error] severity = serious certainty = certain description = An input/output error or another operating system error occurred while checking this file. [range-flag-without-plural-string] severity = normal certainty = certain description = A ``range:`` flag is associated with a message that doesn't have plural string. ``range:`` flags only make sense for translations involving plural forms. references = http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html [redundant-message-flag] severity = pedantic certainty = certain description = A flags associated with one of the messages is redundant, because it's implied by another flag. references = http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html [stray-header-line] severity = important certainty = certain description = The headers contains a line that does not belong to any header. Note that RFC-822-style folding of long headers is not supported. references = http://lists.gnu.org/archive/html/bug-gettext/2012-12/msg00010.html [syntax-error-in-plural-forms] severity = serious certainty = possible description = Value of the Plural-Forms header field could not be parsed. It should be in the form ``nplurals=``\ *n*\ ``; plural=``\ *expression*. references = http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html [syntax-error-in-po-file] severity = serious certainty = possible description = This file couldn't be parsed a PO file. In some rare cases this is due to incorrect or missing encoding declaration. references = http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html http://bugs.debian.org/692283 [syntax-error-in-unused-plural-forms] severity = important certainty = possible description = Value of the Plural-Forms header field could not be parsed. (But there are no translated messages which use plural forms.) It should be in the form ``nplurals=``\ *n*\ ``; plural=``\ *expression*. references = http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html [unable-to-determine-language] severity = normal certainty = wild-guess description = i18nspector was unable to determine language of this file. Absence of this information will prevent it from performing further checks. [unexpected-flag-for-header-entry] severity = normal certainty = possible description = An unexpected flag is associated with the header entry. The only flag that makes sense for the header entry is ``fuzzy``. references = http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html [unknown-encoding] severity = important certainty = possible description = This file declares an encoding that couldn't be recognized by i18nspector. It might be a typo. Absence of encoding information will prevent i18nspector from performing further checks. [unknown-file-type] severity = normal certainty = wild-guess description = File format of this file couldn't be recognized. It might be a bug in i18nspector. [unknown-header-field] severity = minor certainty = wild-guess description = The header field name is unknown to i18nspector. It might be a typo or a capitalization error (header field names are case-sensitive). references = http://lists.gnu.org/archive/html/bug-gettext/2012-12/msg00010.html [unknown-message-flag] severity = normal certainty = wild-guess description = An unknown flag is associated with one of the messages. It might be a typo. references = http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html [unknown-poedit-language] severity = minor certainty = wild-guess description = Language declared in X-Poedit-Language couldn't be recognized. It might be a bug in i18nspector. [unrepresentable-characters] severity = serious certainty = possible description = The declared encoding cannot represent all characters commonly used in this language. This is a strong indication that the declared encoding is incorrect. [unusual-character-in-header-entry] severity = important certainty = certain description = The header entry contains an unusual character. This is usually an indication of an encoding problem, such as: . * using ISO 2022 escape sequences, or * using UTF-8 despite declaring an 8-bit encoding. references = http://www.unicode.org/faq/utf_bom.html#bom6 [unusual-character-in-translation] severity = important certainty = possible description = One of the translated messages contains an unusual character. This is usually an indication of an encoding problem, such as: . * using ISO 2022 escape sequences, or * using UTF-8 despite declaring an 8-bit encoding. references = http://www.unicode.org/faq/utf_bom.html#bom6 # vim:ft=dosini i18nspector-0.13.4/data/string-formats0000644000000000000000000000046212312562472017575 0ustar00rootroot00000000000000# This file has been generated automatically by private/update-gettext-data. # Do not edit. # Last update: 2013-07-27 awk boost c csharp elisp gcc-internal gfc-internal java javascript kde librep lisp lua objc object-pascal perl perl-brace php python python-brace qt qt-plural scheme sh smalltalk tcl ycp i18nspector-0.13.4/data/languages0000644000000000000000000010140212312562472016560 0ustar00rootroot00000000000000# This file should describe only the languages that fall into one of the # following categories: # - languages that have a ISO 639-1 two-letter code; # - languages recognized by poedit; # - languages for which real-world PO files exist. # ISO 639-2 codes for collections of languages (see # ) should normally not be added here. [aa] names = Afar [ab] names = Abkhazian characters = а б в г ӷ д е ж з ӡ и к қ ҟ л м н о п ԥ р с т ҭ у ф х ҳ ц ҵ ч ҷ ҽ ҿ ш ы ҩ џ ь ә А Б В Г Ӷ Д Е Ж З Ӡ И К Қ Ҟ Л М Н О П Ԥ Р С Т Ҭ У Ф Х Ҳ Ц Ҵ Ч Ҷ Ҽ Ҿ Ш Ы Ҩ Џ Ь Ә [ace] names = Achinese principal-territory = ID [ach] names = Acoli [ady] names = Adyghe Adygei characters = а б в г д е (ё) ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ы ь э (ю) я А Б В Г Д Е (Ё) Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э (Ю) Я Ӏ [ae] names = Avestan [af] names = Afrikaans principal-territory = ZA plural-forms = nplurals=2; plural=n != 1; [ak] names = Akan principal-territory = GH [am] names = Amharic characters = ሀ ሁ ሂ ሃ ሄ ህ ሆ ለ ሉ ሊ ላ ሌ ል ሎ ሏ ሐ ሑ ሒ ሓ ሔ ሕ ሖ ሗ መ ሙ ሚ ማ ሜ ም ሞ ሟ ሠ ሡ ሢ ሣ ሤ ሥ ሦ ሧ ረ ሩ ሪ ራ ሬ ር ሮ ሯ ሰ ሱ ሲ ሳ ሴ ስ ሶ ሷ ሸ ሹ ሺ ሻ ሼ ሽ ሾ ሿ ቀ ቁ ቂ ቃ ቄ ቅ ቆ ቈ ቊ ቋ ቌ ቍ በ ቡ ቢ ባ ቤ ብ ቦ ቧ ቨ ቩ ቪ ቫ ቬ ቭ ቮ ቯ ተ ቱ ቲ ታ ቴ ት ቶ ቷ ቸ ቹ ቺ ቻ ቼ ች ቾ ቿ ኀ ኁ ኂ ኃ ኄ ኅ ኆ ኈ ኊ ኋ ኌ ኍ ነ ኑ ኒ ና ኔ ን ኖ ኗ ኘ ኙ ኚ ኛ ኜ ኝ ኞ ኟ አ ኡ ኢ ኣ ኤ እ ኦ ኧ ከ ኩ ኪ ካ ኬ ክ ኮ ኰ ኲ ኳ ኴ ኵ ኸ ኹ ኺ ኻ ኼ ኽ ኾ ወ ዉ ዊ ዋ ዌ ው ዎ ዐ ዑ ዒ ዓ ዔ ዕ ዖ ዘ ዙ ዚ ዛ ዜ ዝ ዞ ዟ ዠ ዡ ዢ ዣ ዤ ዥ ዦ ዧ የ ዩ ዪ ያ ዬ ይ ዮ ደ ዱ ዲ ዳ ዴ ድ ዶ ዷ ጀ ጁ ጂ ጃ ጄ ጅ ጆ ጇ ገ ጉ ጊ ጋ ጌ ግ ጎ ጐ ጒ ጓ ጔ ጕ ጠ ጡ ጢ ጣ ጤ ጥ ጦ ጧ ጨ ጩ ጪ ጫ ጬ ጭ ጮ ጯ ጰ ጱ ጲ ጳ ጴ ጵ ጶ ጷ ጸ ጹ ጺ ጻ ጼ ጽ ጾ ጿ ፀ ፁ ፂ ፃ ፄ ፅ ፆ ፈ ፉ ፊ ፋ ፌ ፍ ፎ ፏ ፐ ፑ ፒ ፓ ፔ ፕ ፖ ፗ plural-forms = nplurals=2; plural=n > 1; principal-territory = ET [an] names = Aragonese principal-territory = ES [ang] names = Old English principal-territory = GB [ar] names = Arabic characters = ا ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي [as] names = Assamese characters = অ আ ই ঈ উ ঊ ঋ ৠ ঌ ৡ এ ঐ ও ঔ ক খ গ ঘ ঙ চ ছ জ ঝ ঞ ট ঠ ড ঢ ণ ত ৎ থ দ ধ ন প ফ ব ভ ম য ৰ ল ৱ শ ষ স হ plural-forms = nplurals=2; plural=n != 1; principal-territory = IN [ast] names = Asturian Bable Leonese Asturleonese characters = á é í ñ ó ú (ü) Á É Í Ñ Ó Ú (Ü) plural-forms = nplurals=2; plural=n != 1; principal-territory = ES [av] names = Avaric principal-territory = RU [ay] names = Aymara [az] names = Azerbaijani ç ə ğ ı i ö ş ü Ç Ə Ğ I İ Ö Ş Ü principal-territory = AZ [ba] names = Bashkir [bal] names = Baluchi [be] names = Belarusian characters = а б в г д е ё ж з і й к л м н о п р с т у ў ф х ц ч ш ы ь э ю я А Б В Г Д Е Ё Ж З І Й К Л М Н О П Р С Т У Ў Ф Х Ц Ч Ш Ы Ь Э Ю Я characters@latin = ć č ł ń ś š ŭ ź ž Ć Č Ł Ń Ś Š Ŭ Ź Ž plural-forms = nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; principal-territory = BY [bem] names = Bemba principal-territory = ZM [bg] names = Bulgarian characters = а б в г д е ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ь ю я А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ь Ю Я plural-forms = nplurals=2; plural=n != 1; principal-territory = BG [bho] names = Bhojpuri principal-territory = IN [bi] names = Bislama [bm] names = Bambara principal-territory = ML [bn] names = Bengali characters = অ আ ই ঈ উ ঊ ঋ এ ঐ ও ঔ ক খ গ ঘ ঙ চ ছ জ ঝ ঞ ট ঠ ড ঢ ণ ত থ দ ধ ন প ফ ব ভ ম য র ল শ ষ স হ plural-forms = nplurals=2; plural=n != 1 principal-territory = IN [bo] names = Tibetan principal-territory = CN [br] names = Breton characters = â ê î ô û ù ü ñ Â Ê Î Ô Û Ù Ü Ñ plural-forms = nplurals=2; plural=n > 1; principal-territory = FR [bs] names = Bosnian characters = đ ž ć č š Đ Ž Ć Č Š plural-forms = nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; principal-territory = BA [byn] names = Blin Bilin [ca] names = Catalan Valencian characters = à é è í ï ó ò ú ü ç À É È Í Ï Ó Ò Ú Ü Ç plural-forms = nplurals=2; plural=n != 1 principal-territory = ES [ce] names = Chechen principal-territory = RU [ceb] names = Cebuano principal-territory = PH [ch] names = Chamorro [co] names = Corsican characters = à è ì ï ò ù ü À È Ì Ï Ò Ù Ü principal-territory = FR [cr] names = Cree principal-territory = CA [crh] names = Crimean Tatar Crimean Turkish characters = â ç ğ ı i ñ ö ş ü Â Ç Ğ I İ Ñ Ö Ş Ü [cs] names = Czech characters = á č ď é ě í ň ó ř š ť ú ů ý ž Á Č Ď É Ě Í Ň Ó Ř Š Ť Ú Ů Ý Ž plural-forms = nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2; principal-territory = CZ [csb] names = Kashubian characters = ą ã é ë ł ń ò ó ô ù ż Ą Ã É Ë Ł Ń Ò Ó Ô Ù Ż principal-territory = PL [cu] names = Church Slavic Church Slavonic Old Bulgarian Old Church Slavonic Old Slavonic [cv] names = Chuvash [cy] names = Welsh characters = â ê î ô û ŵ ŷ Â Ê Î Ô Û Ŵ Ŷ principal-territory = GB [da] names = Danish characters = æ ø å Æ Ø Å plural-forms = nplurals=2; plural=n != 1; principal-territory = DK [de] names = German characters = ä ö ü ß Ä Ö Ü plural-forms = nplurals=2; plural=n != 1; principal-territory = DE [doi] names = Dogri principal-territory = IN [dv] names = Dhivehi Divehi Maldivian principal-territory = MV [dz] names = Dzongkha # for simplicity, only consonants are included here; # they should be sufficient for i18nspector purposes: characters = ཀ ཁ ག ང ཅ ཆ ཇ ཉ ཏ ཐ ད ན པ ཕ བ མ ཙ ཚ ཛ ཝ ཞ ཟ འ ཡ ར ལ ཤ ས ཧ ཨ principal-territory = BT [ee] names = Ewe principal-territory = GH [el] names = Greek characters = α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ σ ς τ υ φ χ ψ ω Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ Φ Χ Ψ Ω plural-forms = nplurals=2; plural=n != 1; principal-territory = GR [en] names = English characters@quot = ‘ ’ characters@boldquot = ‘ ’ characters@shaw = 𐑐 𐑑 𐑒 𐑓 𐑔 𐑕 𐑖 𐑗 𐑘 𐑙 𐑚 𐑛 𐑜 𐑝 𐑞 𐑟 𐑠 𐑡 𐑢 𐑣 𐑤 𐑥 𐑦 𐑧 𐑨 𐑩 𐑪 𐑫 𐑬 𐑭 𐑮 𐑯 𐑰 𐑱 𐑲 𐑳 𐑴 𐑵 𐑶 𐑷 𐑸 𐑹 𐑺 𐑻 𐑼 𐑽 𐑾 𐑿 plural-forms = nplurals=2; plural=n != 1; [en_AU] names = Australian English [en_CA] names = Canadian English [en_GB] names = British English [en_US] names = American English [eo] names = Esperanto characters = ĉ ĝ ĥ ĵ ŝ ŭ Ĉ Ĝ Ĥ Ĵ Ŝ Ŭ plural-forms = nplurals=2; plural=n != 1; [es] names = Spanish characters = á é í ñ ó ú (ü) Á É Í Ñ Ó Ú (Ü) plural-forms = nplurals=2; plural=n != 1; principal-territory = ES [et] names = Estonian characters = (š) (ž) õ ä ö ü (Š) (Ž) Õ Ä Ö Ü plural-forms = nplurals=2; plural=n != 1; principal-territory = EE [eu] names = Basque characters = (ç) ñ (Ç) Ñ plural-forms = nplurals=2; plural=n != 1; [fa] names = Persian characters = ا ب پ ت ث ج چ ح خ د ذ ر ز ژ س ش ص ض ط ظ ع غ ف ق ک گ ل م ن و ه ی plural-forms = nplurals=1; plural=0; principal-territory = IR [ff] names = Fulah [fi] names = Finnish characters = (š) (ž) å ä ö (Š) (Ž) Å Ä Ö plural-forms = nplurals=2; plural=n != 1; principal-territory = FI [fil] names = Filipino Pilipino principal-territory = PH [fj] names = Fijian principal-territory = FJ [fo] names = Faroese characters = á ð í ó ú ý æ ø Á Ð Í Ó Ú Ý Æ Ø plural-forms = nplurals=2; plural=n != 1; principal-territory = FO [fr] names = French characters = à â (æ) ç é è ê ë î ï ô (œ) ù û ü ÿ À  (Æ) Ç É È Ê Ë Î Ï Ô (Œ) Ù Û Ü (Ÿ) plural-forms = nplurals=2; plural=n > 1; principal-territory = FR [fur] names = Friulian principal-territory = IT [fy] names = Frisian Western Frisian characters = â ê é ô û ú Â Ê É Ô Û Ú plural-forms = nplurals=2; plural=n != 1; principal-territory = NL [ga] names = Irish characters = á é í ó ú Á É Í Ó Ú # plural-forms = nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2; principal-territory = IE [gaa] names = Ga [gd] names = Gaelic Scottish Gaelic characters = à è ì ò ù À È Ì Ò Ù principal-territory = GB [gez] names = Geez characters = ሀ ሁ ሂ ሃ ሄ ህ ሆ ለ ሉ ሊ ላ ሌ ል ሎ ሏ ሐ ሑ ሒ ሓ ሔ ሕ ሖ ሗ መ ሙ ሚ ማ ሜ ም ሞ ሟ ፙ ሠ ሡ ሢ ሣ ሤ ሥ ሦ ሧ ረ ሩ ሪ ራ ሬ ር ሮ ሯ ፘ ሰ ሱ ሲ ሳ ሴ ስ ሶ ሷ ቀ ቁ ቂ ቃ ቄ ቅ ቆ ቋ በ ቡ ቢ ባ ቤ ብ ቦ ቧ ተ ቱ ቲ ታ ቴ ት ቶ ቷ ኀ ኁ ኂ ኃ ኄ ኅ ኆ ኋ ነ ኑ ኒ ና ኔ ን ኖ ኗ አ ኡ ኢ ኣ ኤ እ ኦ ኧ ከ ኩ ኪ ካ ኬ ክ ኮ ኳ ወ ዉ ዊ ዋ ዌ ው ዎ ዐ ዑ ዒ ዓ ዔ ዕ ዖ ዘ ዙ ዚ ዛ ዜ ዝ ዞ ዟ የ ዩ ዪ ያ ዬ ይ ዮ ደ ዱ ዲ ዳ ዴ ድ ዶ ዷ ገ ጉ ጊ ጋ ጌ ግ ጎ ጓ ጠ ጡ ጢ ጣ ጤ ጥ ጦ ጧ ጰ ጱ ጲ ጳ ጴ ጵ ጶ ጷ ጸ ጹ ጺ ጻ ጼ ጽ ጾ ጿ ፀ ፁ ፂ ፃ ፄ ፅ ፆ ፈ ፉ ፊ ፋ ፌ ፍ ፎ ፏ ፚ ፐ ፑ ፒ ፓ ፔ ፕ ፖ ፗ [gl] names = Galician characters = á é í ñ ó ú Á É Í Ñ Ó Ú plural-forms = nplurals=2; plural=n != 1; [gn] names = Guarani [gu] names = Gujarati characters = અ આ ઇ ઈ ઉ ઊ ઋ એ ઐ ઓ ઔ ક ખ ગ ઘ ઙ ચ છ જ ઝ ઞ ટ ઠ ડ ઢ ણ ત થ દ ધ ન પ ફ બ ભ મ ય ર લ વ શ ષ સ હ ળ plural-forms = nplurals=2; plural=n != 1; principal-territory = IN [gv] names = Manx [ha] names = Hausa [haw] names = Hawaiian [he] names = Hebrew characters = א ב ג ד ה ו ז ח ט י כ ל מ נ ס ע פ צ ק ר ש ת plural-forms = nplurals=2; plural=n != 1; principal-territory = IL [hi] names = Hindi characters = अ आ इ ई उ ऊ ए ऐ ओ औ क ख ख़ ग ग॒ ग़ घ ङ च छ ज ज॒ ज़ झ ञ ट ठ ड ड॒ ड़ ढ ढ़ ण त थ द ध न प फ फ़ ब ब॒ भ म य र ल व श ष स ह plural-forms = nplurals=2; plural=n != 1; principal-territory = IN [ho] names = Hiri Motu [hr] names = Croatian characters = đ ž ć č š Đ Ž Ć Č Š plural-forms = nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; principal-territory = HR [ht] names = Haitian Haitian Creole principal-territory = HT [hu] names = Hungarian characters = á é í ó ö ő ú ü ű Á É Í Ó Ö Ő Ú Ü Ű plural-forms = nplurals=1; plural=0; nplurals=2; plural=n != 1; principal-territory = HU [hy] names = Armenian characters = ա բ գ դ ե զ է ը թ ժ ի լ խ ծ կ հ ձ ղ ճ մ յ ն շ ո չ պ ջ ռ ս վ տ ր ց ւ փ ք և օ ֆ Ա Բ Գ Դ Ե Զ Է Ը Թ Ժ Ի Լ Խ Ծ Կ Հ Ձ Ղ Ճ Մ Յ Ն Շ Ո Չ Պ Ջ Ռ Ս Վ Տ Ր Ց Ւ Փ Ք Օ Ֆ principal-territory = AM [hz] names = Herero [ia] names = Interlingua plural-forms = nplurals=2; plural=n != 1; [id] names = Indonesian plural-forms = nplurals=1; plural=0; principal-territory = ID [ie] names = Interlingue Occidental [ig] names = Igbo principal-territory = NG [ii] names = Nuosu Sichuan Yi principal-territory = CN [ik] names = Inupiaq [ilo] names = Iloko principal-territory = PH [io] names = Ido [is] names = Icelandic characters = á ð é í ó ú ý þ æ ö Á Ð É Í Ó Ú Ý Þ Æ Ö principal-territory = IS [it] names = Italian characters = à è é ì í î ò ó ù ú À È É Ì Í Î Ò Ó Ù Ú plural-forms = nplurals=2; plural=n != 1; principal-territory = IT [iu] names = Inuktitut [ja] names = Japanese characters = # Hiragana: あ い う え お か き く け こ さ し す せ そ た ち つ て と な に ぬ ね の は ひ ふ へ ほ ま み む め も や ゆ よ ら り る れ ろ わ ゐ ゑ を ん # Katakana: ア イ ウ エ オ カ キ ク ケ コ サ シ ス セ ソ タ チ ツ テ ト ナ ニ ヌ ネ ノ ハ ヒ フ ヘ ホ マ ミ ム メ モ ヤ ユ ヨ ラ リ ル レ ロ ワ ヰ ヱ ヲ ン # Kanji (the list of ideograms is incomplete; # only the 100 most often used ones are included here): 以 一 下 化 加 可 解 開 外 確 間 起 検 見 現 後 効 更 行 合 込 再 最 在 作 削 使 始 指 字 時 次 示 自 失 実 者 取 終 集 出 書 除 小 上 場 情 新 数 成 正 生 切 設 先 選 前 全 続 存 他 大 択 値 置 中 追 通 定 的 度 動 読 内 日 入 認 能 敗 発 必 表 不 付 分 文 変 保 報 方 無 名 明 有 用 要 利 理 了 力 plural-forms = nplurals=1; plural=0; principal-territory = JP [jbo] names = Lojban [jv] names = Javanese principal-territory = ID [ka] names = Georgian characters = ა ბ გ დ ე ვ ზ (ჱ) თ ი კ ლ მ ნ (ჲ) ო პ ჟ რ ს ტ (ჳ) უ ფ ქ ღ ყ შ ჩ ც ძ წ ჭ ხ (ჴ) ჯ ჰ (ჵ) (ჶ) (ჷ) (ჺ) (ჸ) (ჹ) plural-forms = nplurals=1; plural=0; principal-territory = GE [kab] names = Kabyle principal-territory = DZ [kg] names = Kongo principal-territory = CD [ki] names = Gikuyu Kikuyu [kj] names = Kuanyama Kwanyama [kk] names = Kazakh characters = а ә б в г ғ д е ё ж з и й к қ л м н ң о ө п р с т у ұ ү ф х һ ц ч ш щ ъ ы і ь э ю я А Ә Б В Г Ғ Д Е Ё Ж З И Й К Қ Л М Н Ң О Ө П Р С Т У Ұ Ү Ф Х Һ Ц Ч Ш Щ Ъ Ы І Ь Э Ю Я plural-forms = nplurals=1; plural=0; principal-territory = KZ [kl] names = Greenlandic Kalaallisut principal-territory = GL [km] names = Central Khmer Khmer # for simplicity, only consonants are included here; # they should be sufficient for i18nspector purposes: characters = ក ខ គ ឃ ង ច ឆ ជ ឈ ញ ដ ឋ ឌ ឍ ណ ត ថ ទ ធ ន ប ផ ព ភ ម យ រ ល វ ឝ ឞ ស ហ ឡ អ plural-forms = nplurals=1; plural=0; principal-territory = KH [kn] names = Kannada characters = ಅ ಆ ಇ ಈ ಉ ಊ ಋ ೠ ಌ ೡ ಎ ಏ ಐ ಒ ಓ ಔ ಕ ಖ ಗ ಘ ಙ ಚ ಛ ಜ ಝ ಞ ಟ ಠ ಡ ಢ ಣ ತ ಥ ದ ಧ ನ ಪ ಫ ಬ ಭ ಮ ಯ ರ ಱ ಲ ವ ಶ ಷ ಸ ಹ ಳ ೞ principal-territory = IN [ko] names = Korean characters = # The list of Hangul syllables is incomplete; # only the 100 most often used ones are included here. 가 경 고 과 구 그 기 나 는 니 다 대 데 도 동 되 된 드 디 라 러 력 로 록 류 를 름 리 마 만 면 명 모 목 미 바 보 부 비 사 상 서 선 설 성 소 수 스 습 시 실 십 아 않 어 없 에 여 오 용 우 원 위 으 은 을 음 의 이 인 일 입 있 자 작 장 재 저 전 정 제 주 중 지 추 치 크 택 터 트 파 표 프 하 한 할 합 해 행 화 plural-forms = nplurals=1; plural=0; principal-territory = KR [kok] names = Konkani principal-territory = IN [kos] names = Kosraean [kr] names = Kanuri principal-territory = NG [ks] names = Kashmiri [ku] names = Kurdish characters = ç ê î ş û Ç Ê Î Ş Û plural-forms = nplurals=2; plural=n != 1; [kv] names = Komi [kw] names = Cornish [ky] names = Kirghiz Kyrgyz characters = а б в г д е ё ж з и й к л м н ң о ө п р с т у ү ф х ц ч ш щ ъ ы ь э ю я А Б В Г Д Е Ё Ж З И Й К Л М Н Ң О Ө П Р С Т У Ү Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я [la] names = Latin [lb] names = Letzeburgesch Luxembourgish [lg] names = Ganda principal-territory = UG [li] names = Limburgan principal-territory = BE [ln] names = Lingala [lo] names = Lao principal-territory = LA [lt] names = Lithuanian characters = ą č ę ė į š ų ū ž Ą Č Ę Ė Į Š Ų Ū Ž plural-forms = nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2; principal-territory = LT [lu] names = Luba-Katanga principal-territory = CD [lv] names = Latvian characters = ā č ē ģ ī ķ ļ ņ š ū ž Ā Č Ē Ģ Ī Ķ Ļ Ņ Š Ū Ž plural-forms = nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2; principal-territory = LV [mai] names = Maithili plural-forms = nplurals=2; plural=n != 1; principal-territory = IN [mg] names = Malagasy characters = à â é è ê ë ì î ï ñ ô À Â É È Ê Ë Ì Î Ï Ñ Ô plural-forms = nplurals=2; plural=n > 1; principal-territory = MG [mh] names = Marshall Marshallese [mi] names = Maori characters = ā ē ī ō ū Ā Ē Ī Ō Ū principal-territory = NZ [mk] names = Macedonian characters = а б в г д ѓ е ж з ѕ и ј к л љ м н њ о п р с т ќ у ф х ц ч џ ш А Б В Г Д Ѓ Е Ж З Ѕ И Ј К Л Љ М Н Њ О П Р С Т Ќ У Ф Х Ц Ч Џ Ш principal-territory = MK [ml] names = Malayalam characters = അ ആ ഇ ഈ ഉ ഊ ഋ എ ഏ ഐ ഒ ഓ ഔ ക ഖ ഗ ഘ ങ ച ഛ ജ ഝ ഞ ട ഠ ഡ ഢ ണ ത ഥ ദ ധ ന പ ഫ ബ ഭ മ യ ര ല വ ശ ഷ സ ഹ ള ഴ റ plural-forms = nplurals=2; plural=n != 1; principal-territory = IN [mn] names = Mongolian characters = а б в г д е ё ж з и й к л м н о ө п р с т у ү ф х ц ч ш щ ъ ы ь э ю я А Б В Г Д Е Ё Ж З И Й К Л М Н О Ө П Р С Т У Ү Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я plural-forms = nplurals=2; plural=n != 1; principal-territory = MN [mni] names = Manipuri principal-territory = IN [mr] names = Marathi characters = अ आ इ ई उ ऊ ऋ ऌ ए ऐ ऑ ओ औ क ख ग घ ङ च छ ज झ ञ ट ठ ड ढ ण त थ द ध न प फ ब भ म य र ल व श ष स ह ळ plural-forms = nplurals=2; plural=n != 1; principal-territory = IN [ms] names = Malay principal-territory = MY [mt] names = Maltese principal-territory = MT [mus] names = Creek [my] names = Burmese characters = က ခ ဂ ဃ င စ ဆ ဇ ဈ ဉ ည ဋ ဌ ဍ ဎ ဏ တ ထ ဒ ဓ န ပ ဖ ဗ ဘ မ ယ ရ လ ဝ သ ဟ ဠ principal-territory = MM [na] names = Nauru principal-territory = NR [nap] names = Neapolitan principal-territory = IT [nb] names = Norwegian Bokmål characters = æ ø å Æ Ø Å plural-forms = nplurals=2; plural=n != 1; principal-territory = NO [nd] names = North Ndebele [nds] names = Low German Low Saxon characters = ä ö ü ß Ä Ö Ü plural-forms = nplurals=2; plural=n != 1; principal-territory = DE [ne] names = Nepali characters = अ आ इ ई उ ऊ ऋ ए ऐ ओ औ क ख ग घ ङ च छ ज झ ञ ट ठ ड ढ ण त थ द ध न प फ ब भ म य र ल व श ष स ह plural-forms = nplurals=2; plural=n != 1; principal-territory = NP [ng] names = Ndonga [nl] names = Dutch Flemish characters = ä ë ï (ij) ö ü Ä Ë Ï (IJ) Ö Ü plural-forms = nplurals=2; plural=n != 1; principal-territory = NL [nn] names = Norwegian Nynorsk characters = æ ø å Æ Ø Å plural-forms = nplurals=2; plural=n != 1; principal-territory = NO [no] names = Norwegian characters = æ ø å Æ Ø Å macrolanguage = nb nn plural-forms = nplurals=2; plural=n != 1; principal-territory = NO [nr] names = South Ndebele principal-territory = ZA [nso] names = Pedi Sepedi Northern Sotho principal-territory = ZA [nv] names = Navaho Navajo [ny] names = Chichewa Chewa Nyanja [oc] names = Occitan characters = à á ç è é í ï ò ó ú ü À Á Ç È É Í Ï Ò Ó Ú Ü plural-forms = nplurals=2; plural=n > 1; principal-territory = FR [oj] names = Ojibwa principal-territory = CA [om] names = Oromo [or] names = Oriya characters = ଅ ଆ ଇ ଈ ଉ ଊ ଋ ଏ ଐ ଓ ଔ କ ଖ ଗ ଘ ଙ ଚ ଛ ଜ ଝ ଞ ଟ ଠ ଡ ଢ ଣ ତ ଥ ଦ ଧ ନ ପ ଫ ବ ଭ ମ ଯ ର ଲ ଳ ଶ ଷ ସ ହ plural-forms = nplurals=2; plural=n != 1; principal-territory = IN [os] names = Ossetian Ossetic characters = a ӕ б в г д дж дз е з и й к л м н о п р с т у ф х ц ч ы ъ А Ӕ Б В Г Д ДЖ ДЗ Е З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ы Ъ [pa] names = Panjabi Punjabi characters = ੴ ੳ ਉ ਊ ਓ ਅ ਆ ਐ ਔ ੲ ਇ ਈ ਏ ਸ ਹ ਕ ਖ ਗ ਘ ਙ ਚ ਛ ਜ ਝ ਞ ਟ ਠ ਡ ਢ ਣ ਤ ਥ ਦ ਧ ਨ ਪ ਫ ਬ ਭ ਮ ਯ ਰ ਲ ਵ ੜ plural-forms = nplurals=2; plural=n != 1; principal-territory = IN [pap] names = Papiamento [pi] names = Pali [pl] names = Polish characters = ą ć ę ó ł ń ó ś ż ź Ą Ć Ę Ó Ł Ń Ó Ś Ż Ź plural-forms = nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; principal-territory = PL [ps] names = Pashto Pushto characters = آ آ ب پ ت ټ ث ج چ ح خ څ ځ د ډ ﺫ ﺭ ړ ﺯ ژ ږ س ش ښ ص ض ط ظ ع غ ف ق ک ګ ل م ن ڼ و ه ي ې ی ۍ ئ plural-forms = nplurals=2; plural=n != 1; principal-territory = AF [pt] names = Portuguese characters = á â ã à ç é ê í ó ô õ ú Á  à À Ç É Ê Í Ó Ô Õ Ú plural-forms = nplurals=2; plural=n != 1; principal-territory = PT [pt_BR] names = Brazilian Brazilian Portuguese plural-forms = nplurals=2; plural=n > 1; [qu] names = Quechua [rm] names = Rhaeto-Romance Romansh principal-territory = CH [rn] names = Rundi principal-territory = BI [ro] names = Romanian characters = ă â î ș ț Ă Â Î Ș Ț plural-forms = nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2; principal-territory = RO [ro_MD] names = Moldavian Moldovan plural-forms = nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2; [ru] names = Russian characters = а б в г д е ё ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ы ь э ю я А Б В Г Д Е Ё Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я plural-forms = nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; principal-territory = RU [rw] names = Kinyarwanda plural-forms = nplurals=2; plural=n != 1; [sa] names = Sanskrit principal-territory = IN [sat] names = Santali principal-territory = IN [sc] names = Sardinian principal-territory = IT [sco] names = Scots [sd] names = Sindhi characters = جھ ڄ ج پ ث ٺ ٽ ٿ ت ڀ ٻ ب ا ڙ ر ذ ڍ ڊ ڏ ڌ د خ ح ڇ چ ڃ ق ڦ ف غ ع ظ ط ض ص ش س ز ڙھ ي ه و ڻ ن م ل ڱ گھ ڳ گ ک ڪ characters@devanagari = अ आ इ ई उ ऊ ए ऐ ओ औ क ख ख़ ग ग॒ ग़ घ ङ च छ ज ज॒ ज़ झ ञ ट ठ ड ड॒ ड़ ढ ढ़ ण त थ द ध न प फ फ़ ब ब॒ भ म य र ल व श ष स ह [se] names = Northern Sami characters = á č đ ŋ š ŧ ž Á Č Đ Ŋ Š Ŧ Ž [sg] names = Sango Sangro principal-territory = CF [shn] names = Shan principal-territory = MM [si] names = Sinhala Sinhalese # for simplicity, only consonants are included here; # they should be sufficient for i18nspector purposes: characters = ක ග (ච) ජ ට ඩ ණ ත ද න ප බ ම ය ර ල ව ස හ ළ plural-forms = nplurals=2; plural=n != 1; principal-territory = LK [sk] names = Slovak characters = á ä č ď ž é í ĺ ľ ň ó ô ŕ š ť ú ý ž Á Ä Č Ď Ž É Í Ĺ Ľ Ň Ó Ô Ŕ Š Ť Ú Ý Ž # plural-forms = nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2; principal-territory = SK [sl] names = Slovenian characters = č š ž Č Š Ž # plural-forms = nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3; principal-territory = SI [sm] names = Samoan [sn] names = Shona [so] names = Somali principal-territory = SO [sq] names = Albanian characters = ç ë Ç Ë plural-forms = nplurals=2; plural=n != 1; principal-territory = AL [sr] names = Serbian characters = а б в г д ђ е ж з и ј к л љ м н њ о п р с т ћ у ф х ц ч џ ш А Б В Г Д Ђ Е Ж З И Ј К Л Љ М Н Њ О П Р С Т Ћ У Ф Х Ц Ч Џ Ш characters@latin = đ ž ć č š Đ Ž Ć Č Š characters@ijekavianlatin = đ ž ć č š Đ Ž Ć Č Š plural-forms = nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; principal-territory = RS [ss] names = Swati Siswati [st] names = Sesotho Southern Sotho [su] names = Sundanese [sv] names = Swedish characters = å ä ö Å Ä Ö plural-forms = nplurals=2; plural=n != 1; principal-territory = SE [sw] names = Swahili [ta] names = Tamil characters = அ ஆ இ ஈ உ ஊ எ ஏ ஐ ஒ ஓ ஔ க ங ச ஞ ட ண த ந ப ம ய ர ல வ ழ ள ற ன ஜ ஶ ஷ ஸ ஹ plural-forms = nplurals=2; plural=n != 1; [te] names = Telugu characters = అ ఆ ఇ ఈ ఉ ఊ ఋ ౠ ఎ ఏ ఐ ఒ ఓ ఔ క ఖ గ ఘ ఙ చ ఛ జ ఝ ఞ ట ఠ డ ఢ ణ త థ ద ధ న ప ఫ బ భ మ య ర ఱ ల వ శ ష స హ ళ plural-forms = nplurals=2; plural=n != 1; principal-territory = IN [tet] names = Tetum principal-territory = ID [tg] names = Tajik characters = а б в г ғ д е ё ж з и ӣ й к қ л м н о п р с т у ӯ ф х ҳ ч ҷ ш ъ э ю я А Б В Г Ғ Д Е Ё Ж З И Ӣ Й К Қ Л М Н О П Р С Т У Ӯ Ф Х Ҳ Ч Ҷ Ш Ъ Э Ю Я plural-forms = nplurals=2; plural=n != 1; principal-territory = TJ [th] names = Thai characters = ก ข ฃ ค ฅ ฆ ง จ ฉ ช ซ ฌ ญ ฎ ฏ ฐ ฑ ฒ ณ ด ต ถ ท ธ น บ ป ผ ฝ พ ฟ ภ ม ย ร ล ว ศ ษ ส ห ฬ อ ฮ plural-forms = nplurals=1; plural=0; principal-territory = TH [ti] names = Tigrinya characters = ሀ ሁ ሂ ሃ ሄ ህ ሆ ለ ሉ ሊ ላ ሌ ል ሎ ሐ ሑ ሒ ሓ ሔ ሕ ሖ መ ሙ ሚ ማ ሜ ም ሞ ሠ ሡ ሢ ሣ ሤ ሥ ሦ ረ ሩ ሪ ራ ሬ ር ሮ ሰ ሱ ሲ ሳ ሴ ስ ሶ ሸ ሹ ሺ ሻ ሼ ሽ ሾ ቀ ቁ ቂ ቃ ቄ ቅ ቆ ቈ ቊ ቋ ቌ ቍ ቐ ቑ ቒ ቓ ቔ ቕ ቖ ቘ ቚ ቛ ቜ ቝ በ ቡ ቢ ባ ቤ ብ ቦ ቨ ቩ ቪ ቫ ቬ ቭ ቮ ተ ቱ ቲ ታ ቴ ት ቶ ቸ ቹ ቺ ቻ ቼ ች ቾ ኀ ኁ ኂ ኃ ኄ ኅ ኆ ኈ ኊ ኋ ኌ ኍ ነ ኑ ኒ ና ኔ ን ኖ ኘ ኙ ኚ ኛ ኜ ኝ ኞ አ ኡ ኢ ኣ ኤ እ ኦ ከ ኩ ኪ ካ ኬ ክ ኮ ኰ ኲ ኳ ኴ ኵ ኸ ኹ ኺ ኻ ኼ ኽ ኾ ዀ ዂ ዃ ዄ ዅ ወ ዉ ዊ ዋ ዌ ው ዎ ዐ ዑ ዒ ዓ ዔ ዕ ዖ ዘ ዙ ዚ ዛ ዜ ዝ ዞ ዠ ዡ ዢ ዣ ዤ ዥ ዦ የ ዩ ዪ ያ ዬ ይ ዮ ደ ዱ ዲ ዳ ዴ ድ ዶ ጀ ጁ ጂ ጃ ጄ ጅ ጆ ገ ጉ ጊ ጋ ጌ ግ ጎ ጐ ጒ ጓ ጔ ጕ ጠ ጡ ጢ ጣ ጤ ጥ ጦ ጨ ጩ ጪ ጫ ጬ ጭ ጮ ጰ ጱ ጲ ጳ ጴ ጵ ጶ ጸ ጹ ጺ ጻ ጼ ጽ ጾ ፀ ፁ ፂ ፃ ፄ ፅ ፆ ፈ ፉ ፊ ፋ ፌ ፍ ፎ ፐ ፑ ፒ ፓ ፔ ፕ ፖ [tig] names = Tigre characters = ሀ ሁ ሂ ሃ ሄ ህ ሆ ለ ሉ ሊ ላ ሌ ል ሎ ሐ ሑ ሒ ሓ ሔ ሕ ሖ መ ሙ ሚ ማ ሜ ም ሞ ረ ሩ ሪ ራ ሬ ር ሮ ሰ ሱ ሲ ሳ ሴ ስ ሶ ሸ ሹ ሺ ሻ ሼ ሽ ሾ ቀ ቁ ቂ ቃ ቄ ቅ ቆ ቈ ቊ ቋ ቌ ቍ በ ቡ ቢ ባ ቤ ብ ቦ ተ ቱ ቲ ታ ቴ ት ቶ ቸ ቹ ቺ ቻ ቼ ች ቾ ኀ ኁ ኂ ኃ ኄ ኅ ኆ ኈ ኊ ኋ ኌ ኍ ነ ኑ ኒ ና ኔ ን ኖ አ ኡ ኢ ኣ ኤ እ ኦ ከ ኩ ኪ ካ ኬ ክ ኮ ኰ ኲ ኳ ኴ ኵ ወ ዉ ዊ ዋ ዌ ው ዎ ዐ ዑ ዒ ዓ ዔ ዕ ዖ ዘ ዙ ዚ ዛ ዜ ዝ ዞ ዠ ዡ ዢ ዣ ዤ ዥ ዦ የ ዩ ዪ ያ ዬ ይ ዮ ደ ዱ ዲ ዳ ዴ ድ ዶ ጀ ጁ ጂ ጃ ጄ ጅ ጆ ገ ጉ ጊ ጋ ጌ ግ ጎ ጐ ጒ ጓ ጔ ጕ ጠ ጡ ጢ ጣ ጤ ጥ ጦ ጨ ጩ ጪ ጫ ጬ ጭ ጮ ጰ ጱ ጲ ጳ ጴ ጵ ጶ ጸ ጹ ጺ ጻ ጼ ጽ ጾ ፈ ፉ ፊ ፋ ፌ ፍ ፎ ፐ ፑ ፒ ፓ ፔ ፕ ፖ [tk] names = Turkmen principal-territory = TM [tl] names = Tagalog chracters = (ñ) (Ñ) plural-forms = nplurals=2; plural=n > 1; principal-territory = PH [tlh] names = Klingon tlhIngan-Hol [tn] names = Setswana Tswana [to] names = Tonga principal-territory = TO [tpi] names = Tok Pisin [tr] names = Turkish Türkçe characters = ç ğ ı i ö ş ü Ç Ğ I İ Ö Ş Ü plural-forms = nplurals=1; plural=0; nplurals=2; plural=n != 1; principal-territory = TR [ts] names = Tsonga [tt] names = Tatar characters = а ә б в г д е ё ж җ з и й к л м н ң о ө п р с т у ү ф х һ ц ч ш щ ъ ы ь э ю я А Ә Б В Г Д Е Ё Ж Җ З И Й К Л М Н Ң О Ө П Р С Т У Ү Ф Х Һ Ц Ч Ш Щ Ъ Ы Ь Э Ю Я characters@iqtelif = ç ğ ı í ñ ö ş ü Ç Ğ İ Í Ñ Ö Ş Ü [tvl] names = Tuvalu [tw] names = Twi [ty] names = Tahitian [tyv] names = Tuvinian characters = а б в г д е ё ж з и й к л м н ң о ө п р с т у ү ф х ц ч ш щ ъ ы ь э ю я А Б В Г Д Е Ё Ж З И Й К Л М Н Ң О Ө П Р С Т У Ү Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я [ug] names = Uighur Uyghur characters = ا ە ب پ ت ج چ خ د ر ز ژ س ش غ ف ق ك گ ڭ ل م ن ھ و ۇ ۆ ۈ ۋ ې ى ي plural-forms = nplurals=1; plural=0; principal-territory = CN [uk] names = Ukrainian characters = а б в г ґ д е є ж з и і ї й к л м н о п р с т у ф х ц ч ш щ ь ю я А Б В Г Ґ Д Е Є Ж З И І Ї Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ь Ю Я plural-forms = nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; principal-territory = UA [ur] names = Urdu characters = ا ب پ ت ٹ ث ج چ ح خ د ڈ ذ ر ڑ ز ژ س ش ص ض ط ظ ع غ ف ق ک گ ل م ن و ہ ھ ء ی ے plural-forms = nplurals=2; plural=n != 1; principal-territory = PK [uz] names = Uzbek characters = oʻ gʻ ʼ Oʻ Gʻ characters@cyrillic = а б д е э ф г ҳ и ж к л м н о п қ р с т у в х й з ў ғ ш ч ъ ё ю я А Б Д Е Э Ф Г Ҳ И Ж К Л М Н О П Қ Р С Т У В Х Й З Ў Ғ Ш Ч Ё Ю Я principal-territory = UZ [ve] names = Venda principal-territory = ZA [vi] names = Vietnamese characters = à ả ã á ạ ă ằ ẳ ẵ ắ ặ â ầ ẩ ẫ ấ ậ đ è ẻ ẽ é ẹ ê ề ể ễ ế ệ ì ỉ ĩ í ị ò ỏ õ ó ọ ô ồ ổ ỗ ố ộ ơ ờ ở ỡ ớ ợ ù ủ ũ ú ụ ư ừ ử ữ ứ ự ỳ ỷ ỹ ý ỵ À Ả à Á Ạ Ă Ằ Ẳ Ẵ Ắ Ặ  Ầ Ẩ Ẫ Ấ Ậ Đ È Ẻ Ẽ É Ẹ Ê Ề Ể Ễ Ế Ệ Ì Ỉ Ĩ Í Ị Ò Ỏ Õ Ó Ọ Ô Ồ Ổ Ỗ Ố Ộ Ơ Ờ Ở Ỡ Ớ Ợ Ù Ủ Ũ Ú Ụ Ư Ừ Ử Ữ Ứ Ự Ỳ Ỷ Ỹ Ý Ỵ plural-forms = nplurals=1; plural=0; principal-territory = VN [vo] names = Volapük characters = ä ö ü Ä Ö Ü [wa] names = Walloon characters = â å ç è é ê î ô û Â Å Ç È É Ê Î Ô Û principal-territory = BE [wal] names = Wolaitta Wolaytta principal-territory = ET [wo] names = Wolof [xh] names = Xhosa plural-forms = nplurals=2; plural=n != 1; [yi] names = Yiddish [yo] names = Yoruba [za] names = Chuang Zhuang [zh] names = Chinese # The list of Chinese ideograms is incomplete; # only the 100 most often used ones are included here. characters = 保 被 本 表 不 部 查 成 程 出 除 此 存 大 到 的 地 定 度 多 法 方 分 改 格 更 工 果 行 和 或 加 件 建 接 可 了 理 列 面 名 模 目 能 您 其 器 前 取 全 如 入 上 生 失 使 始 式 是 示 所 它 提 通 外 位 未 文 系 下 小 效 新 型 需 序 要 一 移 以 已 用 有 在 找 者 正 支 知 值 指 制 置 中 重 主 字 自 最 作 [zh_CN] names = Chinese (simplified) [zh_HK] names = Chinese (Hong Kong) [zh_TW] names = Chinese (traditional) [zu] names = Zulu # vim:ft=dosini i18nspector-0.13.4/data/iso-codes0000644000000000000000000001105512312562472016503 0ustar00rootroot00000000000000# This file has been generated automatically by private/update-iso-codes. # Do not edit. # iso-codes version: 3.51 # Last update: 2014-03-20 [language-codes] aar = aa abk = ab ace = ach = ada = ady = afh = afr = af ain = aka = ak akk = alb = sq ale = alt = amh = am ang = anp = ara = ar arc = arg = an arm = hy arn = arp = arw = asm = as ast = ava = av ave = ae awa = aym = ay aze = az bak = ba bal = bam = bm ban = baq = eu bas = bej = bel = be bem = ben = bn bho = bik = bin = bis = bi bla = bod = bo bos = bs bra = bre = br bua = bug = bul = bg bur = my byn = cad = car = cat = ca ceb = ces = cs cha = ch chb = che = ce chg = chi = zh chk = chm = chn = cho = chp = chr = chu = cu chv = cv chy = cop = cor = kw cos = co cre = cr crh = csb = cym = cy cze = cs dak = dan = da dar = del = den = deu = de dgr = din = div = dv doi = dsb = dua = dum = dut = nl dyu = dzo = dz efi = egy = eka = ell = el elx = eng = en enm = epo = eo est = et eus = eu ewe = ee ewo = fan = fao = fo fas = fa fat = fij = fj fil = fin = fi fon = fra = fr fre = fr frm = fro = frr = frs = fry = fy ful = ff fur = gaa = gay = gba = geo = ka ger = de gez = gil = gla = gd gle = ga glg = gl glv = gv gmh = goh = gon = gor = got = grb = grc = gre = el grn = gn gsw = guj = gu gwi = hai = hat = ht hau = ha haw = heb = he her = hz hil = hin = hi hit = hmn = hmo = ho hrv = hr hsb = hun = hu hup = hye = hy iba = ibo = ig ice = is ido = io iii = ii iku = iu ile = ie ilo = ina = ia ind = id inh = ipk = ik isl = is ita = it jav = jv jbo = jpn = ja jpr = jrb = kaa = kab = kac = kal = kl kam = kan = kn kas = ks kat = ka kau = kr kaw = kaz = kk kbd = kha = khm = km kho = kik = ki kin = rw kir = ky kmb = kok = kom = kv kon = kg kor = ko kos = kpe = krc = krl = kru = kua = kj kum = kur = ku kut = lad = lah = lam = lao = lo lat = la lav = lv lez = lim = li lin = ln lit = lt lol = loz = ltz = lb lua = lub = lu lug = lg lui = lun = luo = lus = mac = mk mad = mag = mah = mh mai = mak = mal = ml man = mao = mi mar = mr mas = may = ms mdf = mdr = men = mga = mic = min = mkd = mk mlg = mg mlt = mt mnc = mni = moh = mon = mn mos = mri = mi msa = ms mus = mwl = mwr = mya = my myv = nap = nau = na nav = nv nbl = nr nde = nd ndo = ng nds = nep = ne new = nia = niu = nld = nl nno = nn nob = nb nog = non = nor = no nqo = nso = nwc = nya = ny nym = nyn = nyo = nzi = oci = oc oji = oj ori = or orm = om osa = oss = os ota = pag = pal = pam = pan = pa pap = pau = peo = per = fa phn = pli = pi pol = pl pon = por = pt pro = pus = ps que = qu raj = rap = rar = roh = rm rom = ron = ro rum = ro run = rn rup = rus = ru sad = sag = sg sah = sam = san = sa sas = sat = scn = sco = sel = sga = shn = sid = sin = si slk = sk slo = sk slv = sl sma = sme = se smj = smn = smo = sm sms = sna = sn snd = sd snk = sog = som = so sot = st spa = es sqi = sq srd = sc srn = srp = sr srr = ssw = ss suk = sun = su sus = sux = swa = sw swe = sv syc = syr = tah = ty tam = ta tat = tt tel = te tem = ter = tet = tgk = tg tgl = tl tha = th tib = bo tig = tir = ti tiv = tkl = tlh = tli = tmh = tog = ton = to tpi = tsi = tsn = tn tso = ts tuk = tk tum = tur = tr tvl = twi = tw tyv = udm = uga = uig = ug ukr = uk umb = urd = ur uzb = uz vai = ven = ve vie = vi vol = vo vot = wal = war = was = wel = cy wln = wa wol = wo xal = xho = xh yao = yap = yid = yi yor = yo zap = zbl = zen = zha = za zho = zh zul = zu zun = zza = [territory-codes] AD = AE = AF = AG = AI = AL = AM = AO = AQ = AR = AS = AT = AU = AW = AX = AZ = BA = BB = BD = BE = BF = BG = BH = BI = BJ = BL = BM = BN = BO = BQ = BR = BS = BT = BV = BW = BY = BZ = CA = CC = CD = CF = CG = CH = CI = CK = CL = CM = CN = CO = CR = CU = CV = CW = CX = CY = CZ = DE = DJ = DK = DM = DO = DZ = EC = EE = EG = EH = ER = ES = ET = FI = FJ = FK = FM = FO = FR = GA = GB = GD = GE = GF = GG = GH = GI = GL = GM = GN = GP = GQ = GR = GS = GT = GU = GW = GY = HK = HM = HN = HR = HT = HU = ID = IE = IL = IM = IN = IO = IQ = IR = IS = IT = JE = JM = JO = JP = KE = KG = KH = KI = KM = KN = KP = KR = KW = KY = KZ = LA = LB = LC = LI = LK = LR = LS = LT = LU = LV = LY = MA = MC = MD = ME = MF = MG = MH = MK = ML = MM = MN = MO = MP = MQ = MR = MS = MT = MU = MV = MW = MX = MY = MZ = NA = NC = NE = NF = NG = NI = NL = NO = NP = NR = NU = NZ = OM = PA = PE = PF = PG = PH = PK = PL = PM = PN = PR = PS = PT = PW = PY = QA = RE = RO = RS = RU = RW = SA = SB = SC = SD = SE = SG = SH = SI = SJ = SK = SL = SM = SN = SO = SR = SS = ST = SV = SX = SY = SZ = TC = TD = TF = TG = TH = TJ = TK = TL = TM = TN = TO = TR = TT = TV = TW = TZ = UA = UG = UM = US = UY = UZ = VA = VC = VE = VG = VI = VN = VU = WF = WS = YE = YT = ZA = ZM = ZW = # vim:ft=dosini i18nspector-0.13.4/data/header-fields0000644000000000000000000000065312312562472017314 0ustar00rootroot00000000000000# This file has been generated automatically by # private/update-header-fields. Do not edit. # # The following string extraction tools have been used: # * pygettext.py (xgettext for Python) 1.5 # * xgettext (GNU gettext-tools) 0.18.3 Content-Transfer-Encoding Content-Type Generated-By Language Language-Team Last-Translator MIME-Version PO-Revision-Date POT-Creation-Date Plural-Forms Project-Id-Version Report-Msgid-Bugs-To i18nspector-0.13.4/data/encodings0000644000000000000000000000176312312562472016574 0ustar00rootroot00000000000000[portable-encodings] # PO files should use only character encodings that are supported by both GNU # libc and GNU libiconv. This section lists all of them. Unfortunately, some of # these encodings are not supported by Python. These are marked as "not-python". # http://git.savannah.gnu.org/cgit/gettext.git/tree/gettext-tools/src/po-charset.c?id=v0.18.3#n57 ASCII = US-ASCII = ANSI_X3.4-1968 = ISO-8859-1 = ISO-8859-2 = ISO-8859-3 = ISO-8859-4 = ISO-8859-5 = ISO-8859-6 = ISO-8859-7 = ISO-8859-8 = ISO-8859-9 = ISO-8859-13 = ISO-8859-14 = ISO-8859-15 = KOI8-R = KOI8-U = KOI8-T = not-python CP850 = CP866 = CP874 = CP932 = CP949 = CP950 = CP1250 = CP1251 = CP1252 = CP1253 = CP1254 = CP1255 = CP1256 = CP1257 = GB2312 = EUC-JP = EUC-KR = EUC-TW = not-python BIG5 = BIG5-HKSCS = GBK = GB18030 = SHIFT_JIS = JOHAB = TIS-620 = VISCII = not-python GEORGIAN-PS = not-python UTF-8 = [extra-encodings] # encodings that are used by real-world PO/MO files, # but are not known to Python KOI8-RU = # vim:ft=dosini i18nspector-0.13.4/data/control-characters0000644000000000000000000000113312312562472020407 0ustar00rootroot00000000000000[c0] 00 = NUL 01 = SOH 02 = STX 03 = ETX 04 = EOT 05 = ENQ 06 = ACK 07 = BEL 08 = BS 09 = HT 0a = LF 0b = VT 0c = FF 0d = CR 0e = SO 0f = SI 10 = DLE 11 = DC1 12 = DC2 13 = DC3 14 = DC4 15 = NAK 16 = SYN 17 = ETB 18 = CAN 19 = EM 1a = SUB 1b = ESC 1c = FS 1d = GS 1e = RS 1f = US [del] 7f = DEL [c1] 80 = PAD 81 = HOP 82 = BPH 83 = NBH 84 = IND 85 = NEL 86 = SSA 87 = ESA 88 = HTS 89 = HTJ 8a = VTS 8b = PLD 8c = PLU 8d = RI 8e = SS2 8f = SS3 90 = DCS 91 = PU1 92 = PU2 93 = STS 94 = CCH 95 = MW 96 = SPA 97 = EPA 98 = SOS 99 = SGC 9a = SCI 9b = CSI 9c = ST 9d = OSC 9e = PM 9f = APC # vim:ft=dosini i18nspector-0.13.4/data/charmaps/0000755000000000000000000000000012312562472016467 5ustar00rootroot00000000000000i18nspector-0.13.4/data/charmaps/VISCII0000644000000000000000000000074012312562472017401 0ustar00rootroot00000000000000ẲẴẪ ỶỸỴ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ẠẮẰẶẤẦẨẬẼẸẾỀỂỄỆỐỒỔỖỘỢỚỜỞỊỎỌỈỦŨỤỲÕắằặấầẩậẽẹếềểễệốồổỗỠƠộờởịỰỨỪỬơớƯÀÁÂÃẢĂẳẵÈÉÊẺÌÍĨỳĐứÒÓÔạỷừửÙÚỹỵÝỡưàáâãảăữẫèéêẻìíĩỉđựòóôõỏọụùúũủýợỮi18nspector-0.13.4/data/charmaps/KOI8-T0000644000000000000000000000064412312562472017331 0ustar00rootroot00000000000000  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~қғ‚Ғ„…†‡￾‰ҳ‹ҲҷҶ￾Қ‘’“”•–—￾™￾›￾￾￾￾￾ӯӮё¤ӣ¦§￾￾￾«¬­®￾°±²Ё￾Ӣ¶·￾№￾»￾￾￾©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪi18nspector-0.13.4/data/charmaps/KOI8-RU0000644000000000000000000000065512312562472017456 0ustar00rootroot00000000000000  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓“■∙”—№™ »®«·¤═║╒ёє╔ії╗╘╙╚╛ґў╞╟╠╡ЁЄ╣ІЇ╦╧╨╩╪ҐЎ©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪi18nspector-0.13.4/data/charmaps/GEORGIAN-PS0000644000000000000000000000066612312562472020135 0ustar00rootroot00000000000000  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿აბგდევზჱთიკლმნჲოპჟრსტჳუფქღყშჩცძწჭხჴჯჰჵæçèéêëìíîïðñòóôõö÷øùúûüýþÿi18nspector-0.13.4/Makefile0000644000000000000000000000414512312562472015424 0ustar00rootroot00000000000000# Copyright © 2012, 2013 Jakub Wilk # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the “Software”), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. PYTHON = python3 INSTALL = install PREFIX = /usr/local DESTDIR = exe = i18nspector bindir = $(PREFIX)/bin basedir = $(PREFIX)/share/$(exe) libdir = $(basedir)/lib datadir = $(basedir)/data mandir = $(PREFIX)/share/man .PHONY: all all: ; .PHONY: install install: # binary: $(INSTALL) -d -m755 $(DESTDIR)$(bindir) sed -e "s#^basedir_fallback = .*#basedir_fallback = '$(basedir)/'#" $(exe) > $(DESTDIR)$(bindir)/$(exe) chmod 0755 $(DESTDIR)$(bindir)/$(exe) # library: ( cd lib && find . -type f ! -name '*.py[co]' ) \ | sed -e 's#^[.]/##' \ | xargs -t -I {} $(INSTALL) -p -D -m644 lib/{} $(DESTDIR)$(libdir)/{} # data: ( cd data && find . -type f ) \ | sed -e 's#^[.]/##' \ | xargs -t -I {} $(INSTALL) -p -D -m644 data/{} $(DESTDIR)$(datadir)/{} # manual page: $(INSTALL) -p -D -m644 doc/$(exe).1 $(DESTDIR)$(mandir)/man1/$(exe).1 .PHONY: test test: $(PYTHON) ./tests/run-tests -v .PHONY: clean clean: find . -type f -name '*.py[co]' -delete find . -type d -name '__pycache__' -delete # vim:ts=4 sw=4 noet i18nspector-0.13.4/.coveragerc0000644000000000000000000000017712312562472016106 0ustar00rootroot00000000000000[report] exclude_lines = \s+raise misc[.]DataIntegrityError\b \s+raise NotImplementedError\b # vim:ft=dosini