i18nspector-0.26/0000755000000000000000000000000013733665555013640 5ustar00rootroot00000000000000i18nspector-0.26/.coveragerc0000644000000000000000000000032413733665553015756 0ustar00rootroot00000000000000[run] branch = true [report] show_missing = true exclude_lines = # no coverage \A\s+raise misc[.]DataIntegrityError\b \A\s+raise NotImplementedError\b \A\s+pass\Z # vim:ft=dosini ts=4 sts=4 sw=4 et i18nspector-0.26/.pylintrc0000644000000000000000000000173613733665553015512 0ustar00rootroot00000000000000[MASTER] load-plugins = pylint.extensions.check_elif [MESSAGES CONTROL] disable = bad-builtin, bad-continuation, bad-option-value, duplicate-code, fixme, inconsistent-return-statements, invalid-name, len-as-condition, locally-disabled, locally-enabled, no-else-break, no-else-continue, no-else-raise, no-else-return, no-self-use, raise-missing-from, redefined-variable-type, subprocess-popen-preexec-fn, superfluous-parens, too-few-public-methods, too-many-arguments, too-many-branches, too-many-instance-attributes, too-many-lines, too-many-locals, too-many-nested-blocks, too-many-public-methods, too-many-return-statements, too-many-statements, [BASIC] no-docstring-rgx = .* [REPORTS] reports = no score = no msg-template = {path}:{line}: {C}: {symbol} [{obj}] {msg} [FORMAT] max-line-length = 140 expected-line-ending-format = LF # vim:ft=dosini ts=4 sts=4 sw=4 et i18nspector-0.26/Makefile0000644000000000000000000000442613733665553015304 0ustar00rootroot00000000000000# Copyright © 2012-2018 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 = $(if $(shell command -v ginstall;),ginstall,install) PREFIX = /usr/local DESTDIR = bindir = $(PREFIX)/bin basedir = $(PREFIX)/share/i18nspector mandir = $(PREFIX)/share/man .PHONY: all all: ; .PHONY: install install: i18nspector # executable: $(INSTALL) -d -m755 $(DESTDIR)$(bindir) python_exe=$$($(PYTHON) -c 'import sys; print(sys.executable)') && \ sed \ -e "1 s@^#!.*@#!$$python_exe@" \ -e "s#^basedir_fallback = .*#basedir_fallback = '$(basedir)/'#" \ $(<) > $(<).tmp install $(<).tmp $(DESTDIR)$(bindir)/$(<) rm $(<).tmp # library + data: ( find lib data -type f ! -name '*.py[co]' ) \ | xargs -t -I {} $(INSTALL) -p -D -m644 {} $(DESTDIR)$(basedir)/{} ifeq "$(DESTDIR)" "" umask 022 && $(PYTHON) -m compileall -q $(basedir)/lib/ endif ifeq "$(wildcard doc/*.1)" "" # run "$(MAKE) -C doc" to build the manpage else # manual page: $(INSTALL) -p -D -m644 doc/$(<).1 $(DESTDIR)$(mandir)/man1/$(<).1 endif .PHONY: test test: $(PYTHON) ./tests/run-tests -v .PHONY: clean clean: find . -type f -name '*.py[co]' -delete find . -type d -name '__pycache__' -delete rm -f .coverage rm -f *.tmp .error = GNU make is required # vim:ts=4 sts=4 sw=4 noet i18nspector-0.26/data/0000755000000000000000000000000013733665553014547 5ustar00rootroot00000000000000i18nspector-0.26/data/charmaps/0000755000000000000000000000000013733665553016345 5ustar00rootroot00000000000000i18nspector-0.26/data/charmaps/GEORGIAN-PS0000644000000000000000000000066613733665553020013 0ustar00rootroot00000000000000  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿აბგდევზჱთიკლმნჲოპჟრსტჳუფქღყშჩცძწჭხჴჯჰჵæçèéêëìíîïðñòóôõö÷øùúûüýþÿi18nspector-0.26/data/charmaps/KOI8-RU0000644000000000000000000000065513733665553017334 0ustar00rootroot00000000000000  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓“■∙”—№™ »®«·¤═║╒ёє╔ії╗╘╙╚╛ґў╞╟╠╡ЁЄ╣ІЇ╦╧╨╩╪ҐЎ©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪi18nspector-0.26/data/charmaps/KOI8-T0000644000000000000000000000064413733665553017207 0ustar00rootroot00000000000000  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~қғ‚Ғ„…†‡￾‰ҳ‹ҲҷҶ￾Қ‘’“”•–—￾™￾›￾￾￾￾￾ӯӮё¤ӣ¦§￾￾￾«¬­®￾°±²Ё￾Ӣ¶·￾№￾»￾￾￾©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪi18nspector-0.26/data/charmaps/VISCII0000644000000000000000000000074013733665553017257 0ustar00rootroot00000000000000ẲẴẪ ỶỸỴ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ẠẮẰẶẤẦẨẬẼẸẾỀỂỄỆỐỒỔỖỘỢỚỜỞỊỎỌỈỦŨỤỲÕắằặấầẩậẽẹếềểễệốồổỗỠƠộờởịỰỨỪỬơớƯÀÁÂÃẢĂẳẵÈÉÊẺÌÍĨỳĐứÒÓÔạỷừửÙÚỹỵÝỡưàáâãảăữẫèéêẻìíĩỉđựòóôõỏọụùúũủýợỮi18nspector-0.26/data/control-characters0000644000000000000000000000113313733665553020265 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.26/data/encodings0000644000000000000000000000176413733665553016453 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". # https://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.26/data/header-fields0000644000000000000000000000065513733665553017174 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.19.5.1 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.26/data/iso-codes0000644000000000000000000001105513733665553016361 0ustar00rootroot00000000000000# This file has been generated automatically by private/update-iso-codes. # Do not edit. # iso-codes version: 3.66 # Last update: 2016-03-19 [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.26/data/languages0000644000000000000000000010155713733665553016451 0ustar00rootroot00000000000000# This file should describe only the languages that fall into one of the # following categories: # - languages that have an 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 # should normally not be added here. # See: https://iso639-3.sil.org/about/scope#Collections%20of%20languages [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 characters = Ċ Ġ ħ Ħ Ż ċ ġ ħ ħ ż 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; # https://savannah.gnu.org/bugs/?45591 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 characters = (ñ) (Ñ) 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.26/data/string-formats0000644000000000000000000000516013733665553017453 0ustar00rootroot00000000000000[formats] # = [example...] awk = %d # https://www.gnu.org/software/gawk/manual/html_node/Printf.html boost = %d # https://www.boost.org/doc/libs/1_68_0/libs/format/doc/format.html c = %d # http://man7.org/linux/man-pages/man3/printf.3.html csharp = {0} # https://docs.microsoft.com/en-us/dotnet/standard/base-types/composite-formatting elisp = %d # https://www.gnu.org/software/emacs/manual/html_node/elisp/Formatting-Strings.html gcc-internal = %d # https://www.gnu.org/software/gettext/manual/html_node/gcc_002dinternal_002dformat.html gfc-internal = %d # https://www.gnu.org/software/gettext/manual/html_node/gfc_002dinternal_002dformat.html java = {0} # https://docs.oracle.com/javase/7/docs/api/java/text/MessageFormat.html # https://ssl.icu-project.org/apiref/icu4j/com/ibm/icu/text/MessageFormat.html javascript = %d # https://www.gnu.org/software/gettext/manual/html_node/javascript_002dformat.html # https://nodejs.org/api/util.html#util_util_format_format kde = %1 # https://techbase.kde.org/Development/Tutorials/Localization/i18n kde-kuit = %1 # https://api.kde.org/frameworks/ki18n/html/prg_guide.html librep = %d # http://librep.sourceforge.net/librep-manual.html#Formatted%20Output lisp = ~A # http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm lua = %d # https://www.lua.org/manual/5.2/manual.html#pdf-string.format objc = %d # https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html object-pascal = %d # https://www.freepascal.org/docs-html/rtl/sysutils/format.html perl = %d # https://perldoc.perl.org/functions/sprintf.html perl-brace = {var} # https://metacpan.org/pod/Locale::TextDomain php = %d # https://secure.php.net/manual/en/function.sprintf.php python = %d # https://docs.python.org/2/library/stdtypes.html#string-formatting-operations # https://docs.python.org/3/library/stdtypes.html#old-string-formatting python-brace = {0} {var} # https://docs.python.org/2/library/string.html#formatstrings # https://docs.python.org/3/library/string.html#formatstrings qt = %1 # https://doc.qt.io/qt-5/qstring.html#arg qt-plural = %n # https://doc.qt.io/qt-5/i18n-source-translation.html#handling-plurals scheme = ~A # https://people.csail.mit.edu/jaffer/slib/Format-Specification.html sh = $var # https://www.gnu.org/software/gettext/manual/html_node/sh_002dformat.html smalltalk = %1 # https://www.gnu.org/software/smalltalk/manual-base/html_node/CharacterArray_002dstring-processing.html tcl = %d # https://www.tcl.tk/man/tcl8.6/TclCmd/format.htm ycp = %1 # https://doc.opensuse.org/projects/YaST/SLES11/tdg/sformat.html # vim:ft=dosini i18nspector-0.26/data/tags0000644000000000000000000011612013733665553015431 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 = https://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 = https://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 = https://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 = https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html#index-encoding-of-PO-files [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-initial-comments] severity = minor certainty = possible description = The initial comments contain xgettext or msginit boilerplate. references = https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [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 = https://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 = https://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 = https://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 = https://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 = https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html#index-encoding-of-PO-files https://tools.ietf.org/html/rfc2045#section-5 [c-format-string-argument-type-mismatch] severity = serious certainty = possible description = There's a type mismatch between a C format argument in ``msgid`` and the corresponding format argument in ``msgid_plural``; or between a C format argument in ``msgstr`` and ``msgid``; or between a C format argument in ``msgstr[``\ *N*\ ``]`` and corresponding ``msgid`` or ``msgid_plural``. references = printf(3) https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html [c-format-string-error] severity = serious certainty = possible description = A C format string could not be parsed. references = printf(3) [c-format-string-excess-arguments] severity = serious certainty = possible description = A C format string for ``msgid`` consumes more arguments than ``msgid_plural``; or ``msgstr`` consumes more arguments than ``msgid``; or ``msgstr[``\ *N*\ ``]`` consumes more arguments than corresponding ``msgid`` or ``msgid_plural``. references = printf(3) https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html [c-format-string-missing-arguments] severity = serious certainty = possible description = A C format string for ``msgid`` consumes fewer arguments than ``msgid_plural``; or ``msgstr`` consumes fewer arguments than ``msgid``; or ``msgstr[``\ *N*\ ``]`` consumes fewer arguments than corresponding ``msgid`` or ``msgid_plural``. . Note that in some languages, the commonly used Plural-Forms expression evaluates to the same value for n=1 and n=21, n=31, and so on. Take this Serbian translation for example:: . . 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; . ... . msgid "one byte" . msgid_plural "%d bytes" . msgstr[0] "%d bajt" . msgstr[1] "%d bajta" . msgstr[2] "%d bajtova" . Here ``%d`` should not be replaced with the spelled-out form ``jedan``. Either ``%d`` should be kept, or the Plural-Forms expression should be amended, so that there is a special case for n=1:: . . Plural-Forms: 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 . ... . msgid "one byte" . msgid_plural "%d bytes" . msgstr[0] "%d bajt" . msgstr[1] "%d bajta" . msgstr[2] "%d bajtova" . msgstr[3] "jedan bajt" references = printf(3) https://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html [c-format-string-non-portable-conversion] severity = pedantic certainty = possible description = A C format string uses a conversion specified or length modifier, for which a more portable replacement exists: . * For integer conversions (``%d``, ``%i``, ``%o``, ``%u``, ``%x``, and ``%X``), use the ``ll`` length modifier instead of ``L`` or ``q``. * For floating-point conversions (``%a``, ``%A``, ``%e``, ``%E``, ``%f``, ``%F``, ``%g``, and ``%G``), don't use the ``l`` length modifier. * Use the ``z`` length modifier instead of ``Z``. * Use ``%lc`` instead of ``%C``. * Use ``%ls`` instead of ``%S``. references = printf(3) [c-format-string-redundant-flag] severity = pedantic certainty = possible description = A C format string includes a redundant character flag. Either it's a duplicate, or it has no effect: . * The ``+`` flag overrides the *space* flag. * The ``-`` flag overrides the ``0`` flag. * If a precision is given, the ``0`` flag has no effect on integer conversions (``%d``, ``%i``, ``%o``, ``%u``, ``%x``, and ``%X``). references = printf(3) [codomain-error-in-plural-forms] severity = serious certainty = certain 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 = https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html [codomain-error-in-unused-plural-forms] severity = normal certainty = certain 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 = https://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 = https://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 = https://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 = https://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 = https://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. For compatibility with very old (<< 0.11) **msgfmt**\ (1) versions, which didn't support fuzzy header entries, it shouldn't be marked as such. references = https://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 = https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html https://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 = https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html https://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html [invalid-content-transfer-encoding] severity = pedantic certainty = certain description = Value of the Content-Transfer-Encoding header field is invalid. It should be ``8bit``. references = https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html https://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 = https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html#index-encoding-of-PO-files https://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 = https://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 = https://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, or a partially qualified domain name. references = https://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, or a partially qualified domain name. references = https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html https://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 = https://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 fewer than two numbers. The syntax is ``range:``\ *min*\ ``..``\ *max*, where both values are non-negative integers. references = https://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, or a partially qualified domain name. references = https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html https://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 = https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html [leading-junk-in-plural-forms] severity = important certainty = certain description = The Plural-Forms header field contains unexpected text before the ``nplurals=`` string. . GNU gettext runtime ignores such leading junk, but other header parsers might be less liberal in what they accept. [malformed-xml] severity = serious certainty = possible description = The original string or the translated string contains an XML fragment, which is not well-formed. references = https://www.w3.org/TR/REC-xml/#sec-well-formed [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 = https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html https://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 = https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html#index-encoding-of-PO-files https://tools.ietf.org/html/rfc2045#section-5 [no-date-header-field] severity = minor certainty = certain description = The date header field doesn't exist. references = https://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 = https://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 = https://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 = https://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 doesn't exist. It should be to set to ``1.0``. references = https://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 = https://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 = https://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 = https://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 = https://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 = https://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 = https://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 = https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html#index-encoding-list [os-error] severity = serious certainty = certain description = An input/output error or another operating system error occurred while checking this file. [partially-translated-message] severity = serious certainty = possible description = Translation is missing for some plural forms of a message. [perl-brace-format-string-error] severity = serious certainty = possible description = A Perl format string could not be parsed. references = https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html [perl-brace-format-string-missing-argument] severity = serious certainty = possible description = A Perl format string for ``msgid`` doesn't use a named argument that is used in ``msgid_plural``; or ``msgstr`` doesn't use a named argument that is used in ``msgid``; or ``msgstr[``\ *N*\ ``]`` doesn't use a named argument that is used in corresponding ``msgid`` or ``msgid_plural``. . Note that in some languages, the commonly used Plural-Forms expression evaluates to the same value for n=1 and n=21, n=31, and so on. Take this Serbian translation for example:: . . 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; . ... . msgid "one byte" . msgid_plural "{n} bytes" . msgstr[0] "{n} bajt" . msgstr[1] "{n} bajta" . msgstr[2] "{n} bajtova" . Here ``{n}`` should not be replaced with the spelled-out form ``jedan``. Either ``{n}`` should be kept, or the Plural-Forms expression should be amended, so that there is a special case for n=1:: . . Plural-Forms: 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 . ... . msgid "one byte" . msgid_plural "{n} bytes" . msgstr[0] "{n} bajt" . msgstr[1] "{n} bajta" . msgstr[2] "{n} bajtova" . msgstr[3] "jedan bajt" references = https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html https://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html [perl-brace-format-string-unknown-argument] severity = serious certainty = possible description = A Perl format string for ``msgid`` uses a named argument that isn't used in ``msgid_plural``; or ``msgstr`` uses a named argument that isn't used in ``msgid``; or ``msgstr[``\ *N*\ ``]`` uses a named argument that isn't used in corresponding ``msgid`` or ``msgid_plural``. This indicates that the conversion would try to consume an argument that weren't supplied. references = https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html [python-brace-format-string-argument-type-mismatch] severity = serious certainty = possible description = There's a type mismatch between a Python format argument in ``msgid`` and the corresponding format argument in ``msgid_plural``; or between a Python format argument in ``msgstr`` and ``msgid``; or between a Python format argument in ``msgstr[``\ *N*\ ``]`` and ``msgid`` or ``msgid_plural``. references = https://docs.python.org/2/library/string.html#formatstrings [python-brace-format-string-error] severity = serious certainty = possible description = A Python format string could not be parsed. references = https://docs.python.org/2/library/string.html#formatstrings [python-brace-format-string-missing-argument] severity = serious certainty = possible description = A Python format string for ``msgid`` doesn't use a named argument that is used in ``msgid_plural``; or ``msgstr`` doesn't use a named argument that is used in ``msgid``; or ``msgstr[``\ *N*\ ``]`` doesn't use a named argument that is used in corresponding ``msgid`` or ``msgid_plural``. . Note that in some languages, the commonly used Plural-Forms expression evaluates to the same value for n=1 and n=21, n=31, and so on. Take this Serbian translation for example:: . . 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; . ... . msgid "one byte" . msgid_plural "{n} bytes" . msgstr[0] "{n} bajt" . msgstr[1] "{n} bajta" . msgstr[2] "{n} bajtova" . Here ``{n}`` should not be replaced with the spelled-out form ``jedan``. Either ``{n}`` should be kept, or the Plural-Forms expression should be amended, so that there is a special case for n=1:: . . Plural-Forms: 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 . ... . msgid "one byte" . msgid_plural "{n} bytes" . msgstr[0] "{n} bajt" . msgstr[1] "{n} bajta" . msgstr[2] "{n} bajtova" . msgstr[3] "jedan bajt" references = https://docs.python.org/2/library/string.html#formatstrings https://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html [python-brace-format-string-unknown-argument] severity = serious certainty = possible description = A Python format string for ``msgid`` uses a named argument that isn't used in ``msgid_plural``; or ``msgstr`` uses a named argument that isn't used in ``msgid``; or ``msgstr[``\ *N*\ ``]`` uses a named argument that isn't used in corresponding ``msgid`` or ``msgid_plural``. This indicates that the conversion would try to consume an argument that weren't supplied. references = https://docs.python.org/2/library/string.html#formatstrings https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html [python-format-string-argument-number-mismatch] severity = serious certainty = possible description = A Python format string for ``msgid`` consumes more arguments than ``msgid_plural``; or ``msgstr`` consumes more arguments than ``msgid``; or ``msgstr[``\ *N*\ ``]`` consumes more arguments than ``msgid`` or ``msgid_plural``. . Python, unlike C, requires that all unnamed arguments must be consumed during conversion. references = https://docs.python.org/2/library/stdtypes.html#string-formatting-operations https://www.gnu.org/software/gettext/manual/html_node/Python.html#Python [python-format-string-argument-type-mismatch] severity = serious certainty = possible description = There's a type mismatch between a Python format argument in ``msgid`` and the corresponding format argument in ``msgid_plural``; or between a Python format argument in ``msgstr`` and ``msgid``; or between a Python format argument in ``msgstr[``\ *N*\ ``]`` and ``msgid`` or ``msgid_plural``. references = https://docs.python.org/2/library/stdtypes.html#string-formatting-operations [python-format-string-error] severity = serious certainty = possible description = A Python format string could not be parsed. references = https://docs.python.org/2/library/stdtypes.html#string-formatting-operations [python-format-string-missing-argument] severity = serious certainty = possible description = A Python format string for ``msgid`` doesn't use a named argument that is used in ``msgid_plural``; or ``msgstr`` doesn't use a named argument that is used in ``msgid``; or ``msgstr[``\ *N*\ ``]`` doesn't use a named argument that is used in corresponding ``msgid`` or ``msgid_plural``. . Note that in some languages, the commonly used Plural-Forms expression evaluates to the same value for n=1 and n=21, n=31, and so on. Take this Serbian translation for example:: . . 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; . ... . msgid "one byte" . msgid_plural "%(n)d bytes" . msgstr[0] "%(n)d bajt" . msgstr[1] "%(n)d bajta" . msgstr[2] "%(n)d bajtova" . Here ``%d`` should not be replaced with the spelled-out form ``jedan``. Either ``%d`` should be kept, or the Plural-Forms expression should be amended, so that there is a special case for n=1:: . . Plural-Forms: 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 . ... . msgid "one byte" . msgid_plural "%(n)d bytes" . msgstr[0] "%(n)d bajt" . msgstr[1] "%(n)d bajta" . msgstr[2] "%(n)d bajtova" . msgstr[3] "jedan bajt" references = https://docs.python.org/2/library/stdtypes.html#string-formatting-operations https://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html [python-format-string-multiple-unnamed-arguments] severity = serious certainty = possible description = A Python format string uses multiple unnamed arguments (such as ``%d``). The translator might need to reorder the arguments to properly translate the message, but this is not possible with unnamed arguments. Named arguments (such as ``%(num)d``) should be used instead. references = https://docs.python.org/2/library/stdtypes.html#string-formatting-operations https://www.gnu.org/software/gettext/manual/html_node/Python.html#Python [python-format-string-obsolete-conversion] severity = pedantic certainty = possible description = A Python format string uses an obsolete conversion specifier: . * Use ``%d`` instead of ``%u``. references = https://docs.python.org/2/library/stdtypes.html#string-formatting-operations [python-format-string-redundant-flag] severity = pedantic certainty = possible description = A Python format string includes a redundant character flag. Either it's a duplicate, or it has no effect: . * The ``+`` flag overrides the *space* flag. * The ``-`` flag overrides the ``0`` flag. * If a precision is given, the ``0`` flag has no effect on integer conversions (``%d``, ``%i``, ``%o``, ``%u``, ``%x``, and ``%X``). references = https://docs.python.org/2/library/stdtypes.html#string-formatting-operations [python-format-string-redundant-length] severity = pedantic certainty = possible description = A Python format string includes a redundant length modifier. Length modifiers (``h``, ``l``, or ``L``) have no effect in Python. references = https://docs.python.org/2/library/stdtypes.html#string-formatting-operations [python-format-string-redundant-precision] severity = pedantic certainty = possible description = A C format string includes precision that has no effect on the conversion. references = https://docs.python.org/2/library/stdtypes.html#string-formatting-operations [python-format-string-unknown-argument] severity = serious certainty = possible description = A Python format string for ``msgid`` uses a named argument that isn't used in ``msgid_plural``; or ``msgstr`` uses a named argument that isn't used in ``msgid``; or ``msgstr[``\ *N*\ ``]`` uses a named argument that isn't used in corresponding ``msgid`` or ``msgid_plural``. This indicates that the conversion would try to consume an argument that weren't supplied. references = https://docs.python.org/2/library/stdtypes.html#string-formatting-operations https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html [python-format-string-unnamed-plural-argument] severity = wishlist certainty = possible description = A Python format string uses an unnamed arguments (such as ``%d``) in the context of plural forms. The translator might want not to use the numeric argument in the singular form; but this is not possible if the argument is unnamed, because Python, unlike C, requires that all unnamed arguments must be consumed during conversion. Named arguments (such as ``%(n)d``) should be used instead. references = https://docs.python.org/2/library/stdtypes.html#string-formatting-operations https://www.gnu.org/software/gettext/manual/html_node/Python.html#Python [qt-plural-format-mistaken-for-c-format] severity = important certainty = possible description = A ``c-format`` flag is associated with the message, but ``qt-plural-format`` should be used instead. . The only C format directive that the message uses is ``%n``. It is very atypical to use it alone in a C format string. references = https://doc.qt.io/qt-5/i18n-source-translation.html#handling-plurals printf(3) [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 = https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html [redundant-message-flag] severity = pedantic certainty = certain description = A flag associated with one of the messages is redundant, because it's implied by another flag. references = https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html [stray-header-line] severity = important certainty = certain description = The header contains a line that does not belong to any header field. Note that RFC-822-style folding of long headers is not supported. references = https://lists.gnu.org/archive/html/bug-gettext/2012-12/msg00010.html [stray-previous-msgid] severity = minor certainty = certain description = The message entry contains annotations about previous untranslated string (``#| msgid``\ *...*), even though the message is not marked as fuzzy. These annotations are only useful for fuzzy messages, and should be removed when unfuzzying. references = https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html [syntax-error-in-plural-forms] severity = serious certainty = certain description = Value of the Plural-Forms header field could not be parsed. It should be in the form ``nplurals=``\ *n*\ ``; plural=``\ *expression*. references = https://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 = https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html https://bugs.debian.org/692283 [syntax-error-in-unused-plural-forms] severity = important certainty = certain 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 = https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html [trailing-junk-in-plural-forms] severity = important certainty = certain description = The Plural-Forms header field contains unexpected text after the plural expression. . GNU gettext runtime ignores such trailing junk, but other header parsers might be less liberal in what they accept. [translation-in-template] severity = minor certainty = certain description = The PO template file contains a translated message. [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 = https://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 = https://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 = https://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 = https://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 = https://www.unicode.org/faq/utf_bom.html#bom6 [unusual-plural-forms] severity = serious certainty = possible description = The Plural-Forms declaration is incorrect (or unusual), according to i18nspector's linguistic data. [unusual-unused-plural-forms] severity = normal certainty = possible description = The Plural-Forms declaration is incorrect (or unusual), according to i18nspector's linguistic data. (But there are no translated messages which use plural forms.) # vim:ft=dosini i18nspector-0.26/data/timezones0000644000000000000000000000615513733665553016516 0ustar00rootroot00000000000000# This file has been generated automatically by private/update-timezones. # Do not edit. # Timezone database version: 2014e # Last update: 2014-07-07 [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.26/doc/0000755000000000000000000000000013733665556014406 5ustar00rootroot00000000000000i18nspector-0.26/doc/LICENSE0000644000000000000000000000207413733665553015413 0ustar00rootroot00000000000000Copyright © 2012-2020 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. i18nspector-0.26/doc/Makefile0000644000000000000000000000354713733665553016054 0ustar00rootroot00000000000000# Copyright © 2012-2018 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. export LC_ALL=C rst2man = $(notdir $(shell command -v rst2man || echo rst2man.py)) exe = i18nspector .PHONY: all all: $(exe).1 tags.rst: ../data/tags ../private/tags-as-rst > $(@).tmp mv $(@).tmp $(@) $(exe).1: manpage.rst tags.rst $(rst2man) --input-encoding=UTF-8 < $(<) > $(@).tmp perl -pi -e '/^[.]BI\b/ and s/\\fP/\\fR/g' $(@).tmp # work-around for https://bugs.debian.org/806601 perl -pi -e 's/^[.]de1\b/.de/' $(@).tmp # work-around for https://bugs.debian.org/710678 perl -pi -e 's/([a-z])\\[(]aq([a-z])/$$1\x27$$2/g' $(@).tmp # prefer ' to \(aq when used as an apostrophe perl -ni -e 'print unless /^[.]\\" vim:/' $(@).tmp mv $(@).tmp $(@) .PHONY: clean clean: rm -f tags.rst $(exe).1 *.tmp .error = GNU make is required # vim:ts=4 sts=4 sw=4 noet i18nspector-0.26/doc/README0000644000000000000000000000170213733665553015263 0ustar00rootroot00000000000000Overview ======== **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. Prerequisites ============= The following software is needed to run i18nspector: * Python ≥ 3.4; * polib_ ≥ 1.0.0, a gettext catalogs manipulation library; * RPLY_, a parser generator. Additionally, the following software is needed to rebuild the manual page from source: * docutils_ ≥ 0.6. For pip users:: python3 -m pip install polib rply python3 -m pip install docutils For Debian users:: apt-get install python3-polib python3-rply apt-get install python3-docutils .. _polib: https://pypi.org/project/polib/ .. _RPLY: https://pypi.org/project/rply/ .. _docutils: http://docutils.sourceforge.net/ .. vim:ft=rst ts=3 sts=3 sw=3 i18nspector-0.26/doc/changelog0000644000000000000000000007734613733665553016276 0ustar00rootroot00000000000000i18nspector (0.26) unstable; urgency=low * Summary of tag changes: + Added: - perl-brace-format-string-error - perl-brace-format-string-missing-argument - perl-brace-format-string-unknown-argument * Check for errors in Perl brace format strings. https://github.com/jwilk/i18nspector/issues/6 -- Jakub Wilk Sat, 26 Sep 2020 18:25:06 +0200 i18nspector (0.25.9) unstable; urgency=low * Drop support for Python < 3.4. * Fix compatibility with Python 3.9. https://bugs.python.org/issue39337 * Fix spelling and grammar in tag descriptions. * Improve the test suite. -- Jakub Wilk Thu, 06 Aug 2020 10:22:52 +0200 i18nspector (0.25.8) unstable; urgency=low * Fix compatibility with Python 3.8. https://bugs.python.org/issue32892 * Add writing system information for Maltese. * Rephrase help messages for --help, --version. * Improve error handling. * Improve the test suite. -- Jakub Wilk Thu, 21 Feb 2019 22:23:17 +0100 i18nspector (0.25.7) unstable; urgency=low * Drop support for Python < 3.3.3. + Fix “FutureWarning: Possible nested set” warnings. Thanks to Helge Kreutzmann for the bug report. https://bugs.debian.org/916928 https://bugs.python.org/issue30349 * Improve the build system: + Remove the coverage file when cleaning. + Use install(1) to install the executable. + Use ginstall(1), instead of install(1), if it exists. + Add checks against BSD make. (Only GNU make is supported.) + Byte-compile Python code on install. * Improve documentation: + Use HTTPS for doc.qt.io. + Use HTTPS for www.unicode.org. -- Jakub Wilk Thu, 20 Dec 2018 20:02:15 +0100 i18nspector (0.25.6) unstable; urgency=low * Drop support for Python 3.2. * Update various URLs: + Use HTTPS for savannah.gnu.org. + Use HTTPS for unicode.org. + pypi.python.org → pypi.org. + sources.debian.net → sources.debian.org. + Alioth VCS → sources.debian.org. * Improve the test suite. -- Jakub Wilk Fri, 18 May 2018 22:02:55 +0200 i18nspector (0.25.5) unstable; urgency=low * Don't complain about POT-Creation-Date missing in MO files. In the future versions of gettext (>> 0.19.8.1), msgfmt will be removing the POT-Creation-Date header. https://savannah.gnu.org/bugs/?49654 * Improve error handling. -- Jakub Wilk Tue, 22 Aug 2017 21:21:13 +0200 i18nspector (0.25.4) unstable; urgency=low * Fix crash when checking Python brace formats string that have both named and numbered arguments. * Reorder sections in the manual page, as per man-pages(7) recommendations. * Put license into a separate file. -- Jakub Wilk Fri, 23 Jun 2017 18:25:35 +0200 i18nspector (0.25.3) unstable; urgency=low * Rewrite shebang at install time. Thanks to Kyrill Detinov for the bug report. https://github.com/jwilk/i18nspector/issues/1 -- Jakub Wilk Mon, 29 Aug 2016 13:25:33 +0200 i18nspector (0.25.2) unstable; urgency=low * Don't disable stdout line buffering. * Make --version print also versions of Python and the libraries. * Make --version print to stdout, not stderr. https://bugs.python.org/issue18920 * Use /usr/bin/env in shebangs. * Fix compatibility with PyPy 3. * Improve documentation about dependencies. * Improve the test suite. -- Jakub Wilk Sun, 21 Aug 2016 21:33:49 +0200 i18nspector (0.25.1) unstable; urgency=low * Fix compatibility with Python 3.6. -- Jakub Wilk Thu, 16 Jun 2016 11:27:08 +0200 i18nspector (0.25) unstable; urgency=low * Rename --parallel as -j/--jobs. * Make it possible to specify “auto” as the number of processes to use. * Remove empty lines between references in the manual page. * Improve the test suite. -- Jakub Wilk Tue, 31 May 2016 17:24:25 +0200 i18nspector (0.24) unstable; urgency=low * Summary of tag changes: + Added: - python-brace-format-string-argument-type-mismatch - python-brace-format-string-error - python-brace-format-string-missing-argument - python-brace-format-string-unknown-argument * Check for errors in Python brace format strings. * Raise certainty of syntax-error-in-plural-forms and syntax-error-in-unused-plural-forms to “certain”. (The main reason the certainty was only “possible” is that the tag was also triggered by leading and trailing junk, for which there are separate tags since 0.23.) * Check for partially qualified domain names in e-mail addresses. * Add option for parallel execution (--parallel). * Improve the test suite. -- Jakub Wilk Wed, 24 Feb 2016 16:46:20 +0100 i18nspector (0.23) unstable; urgency=low * Summary of tag changes: + Added: - leading-junk-in-plural-forms - trailing-junk-in-plural-forms * Make separate tags for leading and trailing junk in Plural-Forms. * Fix typos in tag descriptions. * Use HTTPS for more URLs. -- Jakub Wilk Sat, 06 Feb 2016 15:15:26 +0100 i18nspector (0.22) unstable; urgency=low * Summary of tag changes: + Renamed: - unusual-plural-forms (from incorrect-plural-forms) - unusual-unused-plural-forms (from incorrect-unused-plural-forms) * Fix typo in a tag description. * Fix typo in the help message. * Update QT documentation URLs. * Fix option formatting in the manual page. * Remove redundant parentheses from some exemplary Plural-Forms. * Improve plural forms codomain checks. -- Jakub Wilk Thu, 21 Jan 2016 21:58:52 +0100 i18nspector (0.21) unstable; urgency=low * Summary of tag changes: + Added: - boilerplate-in-initial-comments * Check for xgettext and msginit boilerplate in initial comments. * Improve error handling. * Improve the test suite. -- Jakub Wilk Thu, 19 Nov 2015 19:20:40 +0100 i18nspector (0.20.1) unstable; urgency=low * Set up temporary cache directory in tests/run-tests. -- Jakub Wilk Tue, 15 Sep 2015 17:38:38 +0200 i18nspector (0.20) unstable; urgency=low * Use RPLY for parsing plural expressions. This should make the parser more robust. * Improve the test suite. -- Jakub Wilk Thu, 10 Sep 2015 21:45:40 +0200 i18nspector (0.19) unstable; urgency=low * Summary of tag changes: + Added: - python-format-string-argument-number-mismatch - python-format-string-argument-type-mismatch - python-format-string-error - python-format-string-missing-argument - python-format-string-multiple-unnamed-arguments - python-format-string-obsolete-conversion - python-format-string-redundant-flag - python-format-string-redundant-length - python-format-string-redundant-precision - python-format-string-unknown-argument - python-format-string-unnamed-plural-argument * Check for errors in Python format strings. * Add “kde-kuit” as a known string format. * Verify that polib version is sufficiently new. * Fix language-team-equal-to-last-translator when there are multiple Last-Translator fields. * Improve descriptions of a few tags. * Improve the test suite. -- Jakub Wilk Mon, 06 Jul 2015 20:29:22 +0200 i18nspector (0.18.1) unstable; urgency=low * Make the plural expression parser more robust. * Improve the test suite. -- Jakub Wilk Mon, 02 Mar 2015 12:25:43 +0100 i18nspector (0.18) unstable; urgency=low * Rename --debian as --unpack-deb. Don't make it default even on Debian(-like) systems. * Make the plural expression parser more robust. * Improve the test suite. -- Jakub Wilk Tue, 27 Jan 2015 23:24:53 +0100 i18nspector (0.17.2) unstable; urgency=low * Fix parsing Language header fields containing commas. * Document -h/--help and --version in the manual page. * Improve the test suite. -- Jakub Wilk Wed, 19 Nov 2014 15:11:06 +0100 i18nspector (0.17.1) unstable; urgency=low * Restore compatibility with polib 1.0.3 and earlier versions. Thanks to Kyrill Detinov for the bug report. * Improve the test suite. -- Jakub Wilk Sat, 18 Oct 2014 17:19:17 +0200 i18nspector (0.17) unstable; urgency=low * Summary of tag changes: + Added: - malformed-xml * Check syntax of PO4A XML fragments. * Check for duplicate or conflicting “range” flags. * Tighten the check for invalid “range” flags. * Make URLs for the Content-Type header field documentation more precise. * Improve the test suite. -- Jakub Wilk Fri, 26 Sep 2014 22:25:14 +0200 i18nspector (0.16) unstable; urgency=low * Summary of tag changes: + Added: - c-format-string-missing-arguments - qt-plural-format-mistaken-for-c-format - stray-previous-msgid * Check for C format strings in msgstr/msgstr_plural[N] consuming fewer arguments than corresponding msgid/msgid_plural. Thanks to Guillem Jover for the bug report. https://bugs.debian.org/753946 * Check for previous msgid annotations (“#| msgid …”) attached to non-fuzzy messages. * Check for plural Qt format string mistakenly tagged as C format strings. * Temper checks for conflicting and redundant message flags: + Don't complain about two different format flags applied to the same message when the formats compatible are (to some extent) compatible. + Don't complain when a positive format flag (-format) and a negative format flag (no--format) apply to the same message. The negative format flag might be still a useful hint for the translator. * Never consider non-ASCII characters and control-characters as part of C format string conversion. * Don't complain about unknown header fields starting with lowercase “x-”. * Improve descriptions of a few tags. * Improve the test suite. -- Jakub Wilk Fri, 22 Aug 2014 19:22:47 +0200 i18nspector (0.15) unstable; urgency=low * Summary of tag changes: + Added: - c-format-string-argument-type-mismatch - c-format-string-error - c-format-string-excess-arguments - c-format-string-non-portable-conversion - c-format-string-redundant-flag - partially-translated-message * Check for errors in C format strings. * Check for inconsistent leading/trailing newlines in translations even when encoding is unknown or broken. * Check for conflict markers in translations even when encoding is unknown or broken. * Check for incomplete translations in messages with plural forms. * Fix calculation of current time. * When emitting unusual-character-in-translation, don't output the translated string (which is likely to contain mojibake), but only the message identifier. * Suggest using “-0000” (rather than “+0000”) to indicate that the offset to local time is unknown. This convention is inspired by RFC 3339 §4.3 and RFC 5322 §3.3. * Improve the test suite. -- Jakub Wilk Fri, 08 Aug 2014 23:00:29 +0200 i18nspector (0.14) unstable; urgency=low * Summary of tag changes: + Added: - translation-in-template * Check for PO template files containing translated messages. * Check for duplicate messages, for problems with message flags, and for empty files even when encoding is unknown or broken. * Check for inconsistent leading/trailing newlines between msgid and msgid_plural even when encoding is unknown or broken. * Improve the test suite. -- Jakub Wilk Wed, 16 Jul 2014 15:28:40 +0200 i18nspector (0.13.5) unstable; urgency=low * Use HTTPS URLs when they are available, in documentation and code. * Don't complain about conflict markers in fuzzy messages. Thanks to Guillem Jover for the bug report. https://bugs.debian.org/753924 -- Jakub Wilk Mon, 07 Jul 2014 15:01:31 +0200 i18nspector (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. https://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 codomain 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. https://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/issues/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 parser. (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/issues/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. https://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 environment 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/issues/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 c1-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. https://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.26/doc/i18nspector.10000644000000000000000000015141113733665556016652 0ustar00rootroot00000000000000.\" Man page generated from reStructuredText. . .TH I18NSPECTOR 1 "2020-09-26" "i18nspector 0.26" "" .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 [\fIoptions\fP] \fIfile\fP [\fIfile\fP …] .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. .SH OPTIONS .INDENT 0.0 .TP .BI \-l \ lang\fR,\fB \ \-\-language \ lang Assume this language. \fIlang\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 \-\-unpack\-deb Allow unpacking Debian (binary or source) packages. .TP .BI \-j \ n\fR,\fB \ \-\-jobs \ n Use \fIn\fP processes in parallel. \fIn\fP can be a positive integer, or \fBauto\fP to determine the number automatically. The default is to use only a single process. .TP .B \-h\fP,\fB \-\-help Show help message and exit. .TP .B \-\-version Show version information and exit. .UNINDENT .SH OUTPUT FORMAT .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 .nf \fI\%https://git.savannah.gnu.org/cgit/gettext.git/tree/ChangeLog.0#n1767\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html#index\-encoding\-of\-PO\-files\fP .fi .sp .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\-initial\-comments .sp The initial comments contain xgettext or msginit boilerplate. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, possible .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html#index\-encoding\-of\-PO\-files\fP \fI\%https://tools.ietf.org/html/rfc2045#section\-5\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS c\-format\-string\-argument\-type\-mismatch .sp There's a type mismatch between a C format argument in \fBmsgid\fP and the corresponding format argument in \fBmsgid_plural\fP; or between a C format argument in \fBmsgstr\fP and \fBmsgid\fP; or between a C format argument in \fBmsgstr[\fP\fIN\fP\fB]\fP and corresponding \fBmsgid\fP or \fBmsgid_plural\fP\&. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fBprintf\fP(3) \fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS c\-format\-string\-error .sp A C format string could not be parsed. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fBprintf\fP(3) .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS c\-format\-string\-excess\-arguments .sp A C format string for \fBmsgid\fP consumes more arguments than \fBmsgid_plural\fP; or \fBmsgstr\fP consumes more arguments than \fBmsgid\fP; or \fBmsgstr[\fP\fIN\fP\fB]\fP consumes more arguments than corresponding \fBmsgid\fP or \fBmsgid_plural\fP\&. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fBprintf\fP(3) \fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS c\-format\-string\-missing\-arguments .sp A C format string for \fBmsgid\fP consumes fewer arguments than \fBmsgid_plural\fP; or \fBmsgstr\fP consumes fewer arguments than \fBmsgid\fP; or \fBmsgstr[\fP\fIN\fP\fB]\fP consumes fewer arguments than corresponding \fBmsgid\fP or \fBmsgid_plural\fP\&. .sp Note that in some languages, the commonly used Plural\-Forms expression evaluates to the same value for n=1 and n=21, n=31, and so on. Take this Serbian translation for example: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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; \&... msgid "one byte" msgid_plural "%d bytes" msgstr[0] "%d bajt" msgstr[1] "%d bajta" msgstr[2] "%d bajtova" .ft P .fi .UNINDENT .UNINDENT .sp Here \fB%d\fP should not be replaced with the spelled\-out form \fBjedan\fP\&. Either \fB%d\fP should be kept, or the Plural\-Forms expression should be amended, so that there is a special case for n=1: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C Plural\-Forms: 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 \&... msgid "one byte" msgid_plural "%d bytes" msgstr[0] "%d bajt" msgstr[1] "%d bajta" msgstr[2] "%d bajtova" msgstr[3] "jedan bajt" .ft P .fi .UNINDENT .UNINDENT .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fBprintf\fP(3) \fI\%https://www.gnu.org/software/gettext/manual/html_node/Translating\-plural\-forms.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS c\-format\-string\-non\-portable\-conversion .sp A C format string uses a conversion specified or length modifier, for which a more portable replacement exists: .INDENT 0.0 .IP \(bu 2 For integer conversions (\fB%d\fP, \fB%i\fP, \fB%o\fP, \fB%u\fP, \fB%x\fP, and \fB%X\fP), use the \fBll\fP length modifier instead of \fBL\fP or \fBq\fP\&. .IP \(bu 2 For floating\-point conversions (\fB%a\fP, \fB%A\fP, \fB%e\fP, \fB%E\fP, \fB%f\fP, \fB%F\fP, \fB%g\fP, and \fB%G\fP), don't use the \fBl\fP length modifier. .IP \(bu 2 Use the \fBz\fP length modifier instead of \fBZ\fP\&. .IP \(bu 2 Use \fB%lc\fP instead of \fB%C\fP\&. .IP \(bu 2 Use \fB%ls\fP instead of \fB%S\fP\&. .UNINDENT .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fBprintf\fP(3) .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, possible .UNINDENT .UNINDENT .SS c\-format\-string\-redundant\-flag .sp A C format string includes a redundant character flag. Either it's a duplicate, or it has no effect: .INDENT 0.0 .IP \(bu 2 The \fB+\fP flag overrides the \fIspace\fP flag. .IP \(bu 2 The \fB\-\fP flag overrides the \fB0\fP flag. .IP \(bu 2 If a precision is given, the \fB0\fP flag has no effect on integer conversions (\fB%d\fP, \fB%i\fP, \fB%o\fP, \fB%u\fP, \fB%x\fP, and \fB%X\fP). .UNINDENT .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fBprintf\fP(3) .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, 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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, certain .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Creating\-Compendia.html#Creating\-Compendia\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Creating\-Compendia.html#Creating\-Compendia\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/PO\-Files.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .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. For compatibility 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 .nf \fI\%https://git.savannah.gnu.org/cgit/gettext.git/tree/NEWS?id=v0.11#n44\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP \fI\%https://www.gnu.org/software/gettext/manual/html_node/Translating\-plural\-forms.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP \fI\%https://www.gnu.org/software/gettext/manual/html_node/Translating\-plural\-forms.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, certain .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP \fI\%https://tools.ietf.org/html/rfc2045#section\-6.1\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html#index\-encoding\-of\-PO\-files\fP \fI\%https://tools.ietf.org/html/rfc2045#section\-5\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .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, or a partially qualified domain name. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://tools.ietf.org/html/rfc2606\fP .fi .sp .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, or a partially qualified domain name. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP \fI\%https://tools.ietf.org/html/rfc2606\fP .fi .sp .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 .nf \fI\%https://tools.ietf.org/html/rfc2045#section\-4\fP .fi .sp .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 fewer 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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/PO\-Files.html\fP .fi .sp .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, or a partially qualified domain name. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP \fI\%https://tools.ietf.org/html/rfc2606\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, possible .UNINDENT .UNINDENT .SS leading\-junk\-in\-plural\-forms .sp The Plural\-Forms header field contains unexpected text before the \fBnplurals=\fP string. .sp GNU gettext runtime ignores such leading junk, but other header parsers might be less liberal in what they accept. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, certain .UNINDENT .UNINDENT .SS malformed\-xml .sp The original string or the translated string contains an XML fragment, which is not well\-formed. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://www.w3.org/TR/REC\-xml/#sec\-well\-formed\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, 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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP \fI\%https://tools.ietf.org/html/rfc2045#section\-6.1\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html#index\-encoding\-of\-PO\-files\fP \fI\%https://tools.ietf.org/html/rfc2045#section\-5\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .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 doesn't exist. It should be to set to \fB1.0\fP\&. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://tools.ietf.org/html/rfc2045#section\-4\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Header\-Entry.html#index\-encoding\-list\fP .fi .sp .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 partially\-translated\-message .sp Translation is missing for some plural forms of a message. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS perl\-brace\-format\-string\-error .sp A Perl format string could not be parsed. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS perl\-brace\-format\-string\-missing\-argument .sp A Perl format string for \fBmsgid\fP doesn't use a named argument that is used in \fBmsgid_plural\fP; or \fBmsgstr\fP doesn't use a named argument that is used in \fBmsgid\fP; or \fBmsgstr[\fP\fIN\fP\fB]\fP doesn't use a named argument that is used in corresponding \fBmsgid\fP or \fBmsgid_plural\fP\&. .sp Note that in some languages, the commonly used Plural\-Forms expression evaluates to the same value for n=1 and n=21, n=31, and so on. Take this Serbian translation for example: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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; \&... msgid "one byte" msgid_plural "{n} bytes" msgstr[0] "{n} bajt" msgstr[1] "{n} bajta" msgstr[2] "{n} bajtova" .ft P .fi .UNINDENT .UNINDENT .sp Here \fB{n}\fP should not be replaced with the spelled\-out form \fBjedan\fP\&. Either \fB{n}\fP should be kept, or the Plural\-Forms expression should be amended, so that there is a special case for n=1: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C Plural\-Forms: 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 \&... msgid "one byte" msgid_plural "{n} bytes" msgstr[0] "{n} bajt" msgstr[1] "{n} bajta" msgstr[2] "{n} bajtova" msgstr[3] "jedan bajt" .ft P .fi .UNINDENT .UNINDENT .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html\fP \fI\%https://www.gnu.org/software/gettext/manual/html_node/Translating\-plural\-forms.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS perl\-brace\-format\-string\-unknown\-argument .sp A Perl format string for \fBmsgid\fP uses a named argument that isn't used in \fBmsgid_plural\fP; or \fBmsgstr\fP uses a named argument that isn't used in \fBmsgid\fP; or \fBmsgstr[\fP\fIN\fP\fB]\fP uses a named argument that isn't used in corresponding \fBmsgid\fP or \fBmsgid_plural\fP\&. This indicates that the conversion would try to consume an argument that weren't supplied. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html\fP \fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS python\-brace\-format\-string\-argument\-type\-mismatch .sp There's a type mismatch between a Python format argument in \fBmsgid\fP and the corresponding format argument in \fBmsgid_plural\fP; or between a Python format argument in \fBmsgstr\fP and \fBmsgid\fP; or between a Python format argument in \fBmsgstr[\fP\fIN\fP\fB]\fP and \fBmsgid\fP or \fBmsgid_plural\fP\&. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://docs.python.org/2/library/string.html#formatstrings\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS python\-brace\-format\-string\-error .sp A Python format string could not be parsed. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://docs.python.org/2/library/string.html#formatstrings\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS python\-brace\-format\-string\-missing\-argument .sp A Python format string for \fBmsgid\fP doesn't use a named argument that is used in \fBmsgid_plural\fP; or \fBmsgstr\fP doesn't use a named argument that is used in \fBmsgid\fP; or \fBmsgstr[\fP\fIN\fP\fB]\fP doesn't use a named argument that is used in corresponding \fBmsgid\fP or \fBmsgid_plural\fP\&. .sp Note that in some languages, the commonly used Plural\-Forms expression evaluates to the same value for n=1 and n=21, n=31, and so on. Take this Serbian translation for example: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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; \&... msgid "one byte" msgid_plural "{n} bytes" msgstr[0] "{n} bajt" msgstr[1] "{n} bajta" msgstr[2] "{n} bajtova" .ft P .fi .UNINDENT .UNINDENT .sp Here \fB{n}\fP should not be replaced with the spelled\-out form \fBjedan\fP\&. Either \fB{n}\fP should be kept, or the Plural\-Forms expression should be amended, so that there is a special case for n=1: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C Plural\-Forms: 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 \&... msgid "one byte" msgid_plural "{n} bytes" msgstr[0] "{n} bajt" msgstr[1] "{n} bajta" msgstr[2] "{n} bajtova" msgstr[3] "jedan bajt" .ft P .fi .UNINDENT .UNINDENT .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://docs.python.org/2/library/string.html#formatstrings\fP \fI\%https://www.gnu.org/software/gettext/manual/html_node/Translating\-plural\-forms.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS python\-brace\-format\-string\-unknown\-argument .sp A Python format string for \fBmsgid\fP uses a named argument that isn't used in \fBmsgid_plural\fP; or \fBmsgstr\fP uses a named argument that isn't used in \fBmsgid\fP; or \fBmsgstr[\fP\fIN\fP\fB]\fP uses a named argument that isn't used in corresponding \fBmsgid\fP or \fBmsgid_plural\fP\&. This indicates that the conversion would try to consume an argument that weren't supplied. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://docs.python.org/2/library/string.html#formatstrings\fP \fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS python\-format\-string\-argument\-number\-mismatch .sp A Python format string for \fBmsgid\fP consumes more arguments than \fBmsgid_plural\fP; or \fBmsgstr\fP consumes more arguments than \fBmsgid\fP; or \fBmsgstr[\fP\fIN\fP\fB]\fP consumes more arguments than \fBmsgid\fP or \fBmsgid_plural\fP\&. .sp Python, unlike C, requires that all unnamed arguments must be consumed during conversion. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://docs.python.org/2/library/stdtypes.html#string\-formatting\-operations\fP \fI\%https://www.gnu.org/software/gettext/manual/html_node/Python.html#Python\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS python\-format\-string\-argument\-type\-mismatch .sp There's a type mismatch between a Python format argument in \fBmsgid\fP and the corresponding format argument in \fBmsgid_plural\fP; or between a Python format argument in \fBmsgstr\fP and \fBmsgid\fP; or between a Python format argument in \fBmsgstr[\fP\fIN\fP\fB]\fP and \fBmsgid\fP or \fBmsgid_plural\fP\&. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://docs.python.org/2/library/stdtypes.html#string\-formatting\-operations\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS python\-format\-string\-error .sp A Python format string could not be parsed. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://docs.python.org/2/library/stdtypes.html#string\-formatting\-operations\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS python\-format\-string\-missing\-argument .sp A Python format string for \fBmsgid\fP doesn't use a named argument that is used in \fBmsgid_plural\fP; or \fBmsgstr\fP doesn't use a named argument that is used in \fBmsgid\fP; or \fBmsgstr[\fP\fIN\fP\fB]\fP doesn't use a named argument that is used in corresponding \fBmsgid\fP or \fBmsgid_plural\fP\&. .sp Note that in some languages, the commonly used Plural\-Forms expression evaluates to the same value for n=1 and n=21, n=31, and so on. Take this Serbian translation for example: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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; \&... msgid "one byte" msgid_plural "%(n)d bytes" msgstr[0] "%(n)d bajt" msgstr[1] "%(n)d bajta" msgstr[2] "%(n)d bajtova" .ft P .fi .UNINDENT .UNINDENT .sp Here \fB%d\fP should not be replaced with the spelled\-out form \fBjedan\fP\&. Either \fB%d\fP should be kept, or the Plural\-Forms expression should be amended, so that there is a special case for n=1: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C Plural\-Forms: 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 \&... msgid "one byte" msgid_plural "%(n)d bytes" msgstr[0] "%(n)d bajt" msgstr[1] "%(n)d bajta" msgstr[2] "%(n)d bajtova" msgstr[3] "jedan bajt" .ft P .fi .UNINDENT .UNINDENT .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://docs.python.org/2/library/stdtypes.html#string\-formatting\-operations\fP \fI\%https://www.gnu.org/software/gettext/manual/html_node/Translating\-plural\-forms.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS python\-format\-string\-multiple\-unnamed\-arguments .sp A Python format string uses multiple unnamed arguments (such as \fB%d\fP). The translator might need to reorder the arguments to properly translate the message, but this is not possible with unnamed arguments. Named arguments (such as \fB%(num)d\fP) should be used instead. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://docs.python.org/2/library/stdtypes.html#string\-formatting\-operations\fP \fI\%https://www.gnu.org/software/gettext/manual/html_node/Python.html#Python\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS python\-format\-string\-obsolete\-conversion .sp A Python format string uses an obsolete conversion specifier: .INDENT 0.0 .IP \(bu 2 Use \fB%d\fP instead of \fB%u\fP\&. .UNINDENT .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://docs.python.org/2/library/stdtypes.html#string\-formatting\-operations\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, possible .UNINDENT .UNINDENT .SS python\-format\-string\-redundant\-flag .sp A Python format string includes a redundant character flag. Either it's a duplicate, or it has no effect: .INDENT 0.0 .IP \(bu 2 The \fB+\fP flag overrides the \fIspace\fP flag. .IP \(bu 2 The \fB\-\fP flag overrides the \fB0\fP flag. .IP \(bu 2 If a precision is given, the \fB0\fP flag has no effect on integer conversions (\fB%d\fP, \fB%i\fP, \fB%o\fP, \fB%u\fP, \fB%x\fP, and \fB%X\fP). .UNINDENT .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://docs.python.org/2/library/stdtypes.html#string\-formatting\-operations\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, possible .UNINDENT .UNINDENT .SS python\-format\-string\-redundant\-length .sp A Python format string includes a redundant length modifier. Length modifiers (\fBh\fP, \fBl\fP, or \fBL\fP) have no effect in Python. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://docs.python.org/2/library/stdtypes.html#string\-formatting\-operations\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, possible .UNINDENT .UNINDENT .SS python\-format\-string\-redundant\-precision .sp A C format string includes precision that has no effect on the conversion. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://docs.python.org/2/library/stdtypes.html#string\-formatting\-operations\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, possible .UNINDENT .UNINDENT .SS python\-format\-string\-unknown\-argument .sp A Python format string for \fBmsgid\fP uses a named argument that isn't used in \fBmsgid_plural\fP; or \fBmsgstr\fP uses a named argument that isn't used in \fBmsgid\fP; or \fBmsgstr[\fP\fIN\fP\fB]\fP uses a named argument that isn't used in corresponding \fBmsgid\fP or \fBmsgid_plural\fP\&. This indicates that the conversion would try to consume an argument that weren't supplied. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://docs.python.org/2/library/stdtypes.html#string\-formatting\-operations\fP \fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS python\-format\-string\-unnamed\-plural\-argument .sp A Python format string uses an unnamed arguments (such as \fB%d\fP) in the context of plural forms. The translator might want not to use the numeric argument in the singular form; but this is not possible if the argument is unnamed, because Python, unlike C, requires that all unnamed arguments must be consumed during conversion. Named arguments (such as \fB%(n)d\fP) should be used instead. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://docs.python.org/2/library/stdtypes.html#string\-formatting\-operations\fP \fI\%https://www.gnu.org/software/gettext/manual/html_node/Python.html#Python\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 wishlist, possible .UNINDENT .UNINDENT .SS qt\-plural\-format\-mistaken\-for\-c\-format .sp A \fBc\-format\fP flag is associated with the message, but \fBqt\-plural\-format\fP should be used instead. .sp The only C format directive that the message uses is \fB%n\fP\&. It is very atypical to use it alone in a C format string. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://doc.qt.io/qt\-5/i18n\-source\-translation.html#handling\-plurals\fP \fBprintf\fP(3) .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, possible .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/PO\-Files.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 normal, certain .UNINDENT .UNINDENT .SS redundant\-message\-flag .sp A flag associated with one of the messages is redundant, because it's implied by another flag. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/PO\-Files.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 pedantic, certain .UNINDENT .UNINDENT .SS stray\-header\-line .sp The header contains a line that does not belong to any header field. Note that RFC\-822\-style folding of long headers is not supported. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://lists.gnu.org/archive/html/bug\-gettext/2012\-12/msg00010.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, certain .UNINDENT .UNINDENT .SS stray\-previous\-msgid .sp The message entry contains annotations about previous untranslated string (\fB#| msgid\fP\ \fI\&...\fP), even though the message is not marked as fuzzy. These annotations are only useful for fuzzy messages, and should be removed when unfuzzying. .sp References: .INDENT 0.0 .INDENT 3.5 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/PO\-Files.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, 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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, certain .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/PO\-Files.html\fP \fI\%https://bugs.debian.org/692283\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, certain .UNINDENT .UNINDENT .SS trailing\-junk\-in\-plural\-forms .sp The Plural\-Forms header field contains unexpected text after the plural expression. .sp GNU gettext runtime ignores such trailing junk, but other header parsers might be less liberal in what they accept. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, certain .UNINDENT .UNINDENT .SS translation\-in\-template .sp The PO template file contains a translated message. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 minor, certain .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/PO\-Files.html\fP .fi .sp .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 .nf \fI\%https://lists.gnu.org/archive/html/bug\-gettext/2012\-12/msg00010.html\fP .fi .sp .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 .nf \fI\%https://www.gnu.org/software/gettext/manual/html_node/PO\-Files.html\fP .fi .sp .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 .nf \fI\%https://www.unicode.org/faq/utf_bom.html#bom6\fP .fi .sp .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 .nf \fI\%https://www.unicode.org/faq/utf_bom.html#bom6\fP .fi .sp .UNINDENT .UNINDENT .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 important, possible .UNINDENT .UNINDENT .SS unusual\-plural\-forms .sp The Plural\-Forms declaration is incorrect (or unusual), according to i18nspector's linguistic data. .sp Severity, certainty: .INDENT 0.0 .INDENT 3.5 serious, possible .UNINDENT .UNINDENT .SS unusual\-unused\-plural\-forms .sp The Plural\-Forms declaration is incorrect (or unusual), 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 .SH SEE ALSO .sp \fBmsgfmt\fP(1), particularly the \fB\-c\fP option . .\" Generated by docutils manpage writer. . i18nspector-0.26/doc/manpage.rst0000644000000000000000000000326413733665553016552 0ustar00rootroot00000000000000=========== i18nspector =========== ---------------------------------------------- checking tool for gettext POT, PO and MO files ---------------------------------------------- :manual section: 1 :version: i18nspector 0.26 :date: |date| Synopsis -------- **i18nspector** [*options*] *file* [*file* …] 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. Options ------- -l lang, --language lang Assume this language. *lang* should be a 2- or 3-letter ISO 639 language code, possibly followed by underscore and a 2-letter ISO 3166 territory code. --unpack-deb Allow unpacking Debian (binary or source) packages. -j n, --jobs n Use *n* processes in parallel. *n* can be a positive integer, or ``auto`` to determine the number automatically. The default is to use only a single process. -h, --help Show help message and exit. --version Show version information and exit. Output format ------------- 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.rst .. |date| date:: %Y-%m-%d See also -------- **msgfmt**\ (1), particularly the ``-c`` option .. vim:ts=3 sts=3 sw=3 i18nspector-0.26/doc/tags.rst0000644000000000000000000012174513733665555016107 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: | https://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: | https://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: | https://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: | https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html#index-encoding-of-PO-files 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-initial-comments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The initial comments contain xgettext or msginit boilerplate. References: | https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: minor, possible 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: | https://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: | https://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: | https://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: | https://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: | https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html#index-encoding-of-PO-files | https://tools.ietf.org/html/rfc2045#section-5 Severity, certainty: serious, possible c-format-string-argument-type-mismatch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There's a type mismatch between a C format argument in ``msgid`` and the corresponding format argument in ``msgid_plural``; or between a C format argument in ``msgstr`` and ``msgid``; or between a C format argument in ``msgstr[``\ *N*\ ``]`` and corresponding ``msgid`` or ``msgid_plural``. References: | **printf**\ (3) | https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: serious, possible c-format-string-error ~~~~~~~~~~~~~~~~~~~~~ A C format string could not be parsed. References: | **printf**\ (3) Severity, certainty: serious, possible c-format-string-excess-arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A C format string for ``msgid`` consumes more arguments than ``msgid_plural``; or ``msgstr`` consumes more arguments than ``msgid``; or ``msgstr[``\ *N*\ ``]`` consumes more arguments than corresponding ``msgid`` or ``msgid_plural``. References: | **printf**\ (3) | https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: serious, possible c-format-string-missing-arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A C format string for ``msgid`` consumes fewer arguments than ``msgid_plural``; or ``msgstr`` consumes fewer arguments than ``msgid``; or ``msgstr[``\ *N*\ ``]`` consumes fewer arguments than corresponding ``msgid`` or ``msgid_plural``. Note that in some languages, the commonly used Plural-Forms expression evaluates to the same value for n=1 and n=21, n=31, and so on. Take this Serbian translation for example:: 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; ... msgid "one byte" msgid_plural "%d bytes" msgstr[0] "%d bajt" msgstr[1] "%d bajta" msgstr[2] "%d bajtova" Here ``%d`` should not be replaced with the spelled-out form ``jedan``. Either ``%d`` should be kept, or the Plural-Forms expression should be amended, so that there is a special case for n=1:: Plural-Forms: 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 ... msgid "one byte" msgid_plural "%d bytes" msgstr[0] "%d bajt" msgstr[1] "%d bajta" msgstr[2] "%d bajtova" msgstr[3] "jedan bajt" References: | **printf**\ (3) | https://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html Severity, certainty: serious, possible c-format-string-non-portable-conversion ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A C format string uses a conversion specified or length modifier, for which a more portable replacement exists: * For integer conversions (``%d``, ``%i``, ``%o``, ``%u``, ``%x``, and ``%X``), use the ``ll`` length modifier instead of ``L`` or ``q``. * For floating-point conversions (``%a``, ``%A``, ``%e``, ``%E``, ``%f``, ``%F``, ``%g``, and ``%G``), don't use the ``l`` length modifier. * Use the ``z`` length modifier instead of ``Z``. * Use ``%lc`` instead of ``%C``. * Use ``%ls`` instead of ``%S``. References: | **printf**\ (3) Severity, certainty: pedantic, possible c-format-string-redundant-flag ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A C format string includes a redundant character flag. Either it's a duplicate, or it has no effect: * The ``+`` flag overrides the *space* flag. * The ``-`` flag overrides the ``0`` flag. * If a precision is given, the ``0`` flag has no effect on integer conversions (``%d``, ``%i``, ``%o``, ``%u``, ``%x``, and ``%X``). References: | **printf**\ (3) Severity, certainty: pedantic, 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: | https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: serious, certain 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: | https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: normal, certain conflict-marker-in-header-entry ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The header contains a conflict marker (``#-#-#-#-#`` *…* ``#-#-#-#-#``). The conflict will have to be resolved manually. References: | https://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: | https://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: | https://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: | https://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. For compatibility with very old (<< 0.11) **msgfmt**\ (1) versions, which didn't support fuzzy header entries, it shouldn't be marked as such. References: | https://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: | https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html | https://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: | https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html | https://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html Severity, certainty: serious, certain invalid-content-transfer-encoding ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Value of the Content-Transfer-Encoding header field is invalid. It should be ``8bit``. References: | https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html | https://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: | https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html#index-encoding-of-PO-files | https://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: | https://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: | https://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, or a partially qualified domain name. References: | https://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, or a partially qualified domain name. References: | https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html | https://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: | https://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 fewer than two numbers. The syntax is ``range:``\ *min*\ ``..``\ *max*, where both values are non-negative integers. References: | https://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, or a partially qualified domain name. References: | https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html | https://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: | https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html Severity, certainty: minor, possible leading-junk-in-plural-forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Plural-Forms header field contains unexpected text before the ``nplurals=`` string. GNU gettext runtime ignores such leading junk, but other header parsers might be less liberal in what they accept. Severity, certainty: important, certain malformed-xml ~~~~~~~~~~~~~ The original string or the translated string contains an XML fragment, which is not well-formed. References: | https://www.w3.org/TR/REC-xml/#sec-well-formed Severity, certainty: serious, possible no-content-transfer-encoding-header-field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Content-Transfer-Encoding header field doesn't exist. It should be set to ``8bit``. References: | https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html | https://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: | https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html#index-encoding-of-PO-files | https://tools.ietf.org/html/rfc2045#section-5 Severity, certainty: important, certain no-date-header-field ~~~~~~~~~~~~~~~~~~~~ The date header field doesn't exist. References: | https://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: | https://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: | https://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: | https://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 doesn't exist. It should be to set to ``1.0``. References: | https://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: | https://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: | https://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: | https://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: | https://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: | https://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: | https://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: | https://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html#index-encoding-list Severity, certainty: important, certain os-error ~~~~~~~~ An input/output error or another operating system error occurred while checking this file. Severity, certainty: serious, certain partially-translated-message ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Translation is missing for some plural forms of a message. Severity, certainty: serious, possible perl-brace-format-string-error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A Perl format string could not be parsed. References: | https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html Severity, certainty: serious, possible perl-brace-format-string-missing-argument ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A Perl format string for ``msgid`` doesn't use a named argument that is used in ``msgid_plural``; or ``msgstr`` doesn't use a named argument that is used in ``msgid``; or ``msgstr[``\ *N*\ ``]`` doesn't use a named argument that is used in corresponding ``msgid`` or ``msgid_plural``. Note that in some languages, the commonly used Plural-Forms expression evaluates to the same value for n=1 and n=21, n=31, and so on. Take this Serbian translation for example:: 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; ... msgid "one byte" msgid_plural "{n} bytes" msgstr[0] "{n} bajt" msgstr[1] "{n} bajta" msgstr[2] "{n} bajtova" Here ``{n}`` should not be replaced with the spelled-out form ``jedan``. Either ``{n}`` should be kept, or the Plural-Forms expression should be amended, so that there is a special case for n=1:: Plural-Forms: 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 ... msgid "one byte" msgid_plural "{n} bytes" msgstr[0] "{n} bajt" msgstr[1] "{n} bajta" msgstr[2] "{n} bajtova" msgstr[3] "jedan bajt" References: | https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html | https://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html Severity, certainty: serious, possible perl-brace-format-string-unknown-argument ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A Perl format string for ``msgid`` uses a named argument that isn't used in ``msgid_plural``; or ``msgstr`` uses a named argument that isn't used in ``msgid``; or ``msgstr[``\ *N*\ ``]`` uses a named argument that isn't used in corresponding ``msgid`` or ``msgid_plural``. This indicates that the conversion would try to consume an argument that weren't supplied. References: | https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html | https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: serious, possible python-brace-format-string-argument-type-mismatch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There's a type mismatch between a Python format argument in ``msgid`` and the corresponding format argument in ``msgid_plural``; or between a Python format argument in ``msgstr`` and ``msgid``; or between a Python format argument in ``msgstr[``\ *N*\ ``]`` and ``msgid`` or ``msgid_plural``. References: | https://docs.python.org/2/library/string.html#formatstrings Severity, certainty: serious, possible python-brace-format-string-error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A Python format string could not be parsed. References: | https://docs.python.org/2/library/string.html#formatstrings Severity, certainty: serious, possible python-brace-format-string-missing-argument ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A Python format string for ``msgid`` doesn't use a named argument that is used in ``msgid_plural``; or ``msgstr`` doesn't use a named argument that is used in ``msgid``; or ``msgstr[``\ *N*\ ``]`` doesn't use a named argument that is used in corresponding ``msgid`` or ``msgid_plural``. Note that in some languages, the commonly used Plural-Forms expression evaluates to the same value for n=1 and n=21, n=31, and so on. Take this Serbian translation for example:: 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; ... msgid "one byte" msgid_plural "{n} bytes" msgstr[0] "{n} bajt" msgstr[1] "{n} bajta" msgstr[2] "{n} bajtova" Here ``{n}`` should not be replaced with the spelled-out form ``jedan``. Either ``{n}`` should be kept, or the Plural-Forms expression should be amended, so that there is a special case for n=1:: Plural-Forms: 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 ... msgid "one byte" msgid_plural "{n} bytes" msgstr[0] "{n} bajt" msgstr[1] "{n} bajta" msgstr[2] "{n} bajtova" msgstr[3] "jedan bajt" References: | https://docs.python.org/2/library/string.html#formatstrings | https://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html Severity, certainty: serious, possible python-brace-format-string-unknown-argument ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A Python format string for ``msgid`` uses a named argument that isn't used in ``msgid_plural``; or ``msgstr`` uses a named argument that isn't used in ``msgid``; or ``msgstr[``\ *N*\ ``]`` uses a named argument that isn't used in corresponding ``msgid`` or ``msgid_plural``. This indicates that the conversion would try to consume an argument that weren't supplied. References: | https://docs.python.org/2/library/string.html#formatstrings | https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: serious, possible python-format-string-argument-number-mismatch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A Python format string for ``msgid`` consumes more arguments than ``msgid_plural``; or ``msgstr`` consumes more arguments than ``msgid``; or ``msgstr[``\ *N*\ ``]`` consumes more arguments than ``msgid`` or ``msgid_plural``. Python, unlike C, requires that all unnamed arguments must be consumed during conversion. References: | https://docs.python.org/2/library/stdtypes.html#string-formatting-operations | https://www.gnu.org/software/gettext/manual/html_node/Python.html#Python Severity, certainty: serious, possible python-format-string-argument-type-mismatch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There's a type mismatch between a Python format argument in ``msgid`` and the corresponding format argument in ``msgid_plural``; or between a Python format argument in ``msgstr`` and ``msgid``; or between a Python format argument in ``msgstr[``\ *N*\ ``]`` and ``msgid`` or ``msgid_plural``. References: | https://docs.python.org/2/library/stdtypes.html#string-formatting-operations Severity, certainty: serious, possible python-format-string-error ~~~~~~~~~~~~~~~~~~~~~~~~~~ A Python format string could not be parsed. References: | https://docs.python.org/2/library/stdtypes.html#string-formatting-operations Severity, certainty: serious, possible python-format-string-missing-argument ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A Python format string for ``msgid`` doesn't use a named argument that is used in ``msgid_plural``; or ``msgstr`` doesn't use a named argument that is used in ``msgid``; or ``msgstr[``\ *N*\ ``]`` doesn't use a named argument that is used in corresponding ``msgid`` or ``msgid_plural``. Note that in some languages, the commonly used Plural-Forms expression evaluates to the same value for n=1 and n=21, n=31, and so on. Take this Serbian translation for example:: 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; ... msgid "one byte" msgid_plural "%(n)d bytes" msgstr[0] "%(n)d bajt" msgstr[1] "%(n)d bajta" msgstr[2] "%(n)d bajtova" Here ``%d`` should not be replaced with the spelled-out form ``jedan``. Either ``%d`` should be kept, or the Plural-Forms expression should be amended, so that there is a special case for n=1:: Plural-Forms: 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 ... msgid "one byte" msgid_plural "%(n)d bytes" msgstr[0] "%(n)d bajt" msgstr[1] "%(n)d bajta" msgstr[2] "%(n)d bajtova" msgstr[3] "jedan bajt" References: | https://docs.python.org/2/library/stdtypes.html#string-formatting-operations | https://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html Severity, certainty: serious, possible python-format-string-multiple-unnamed-arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A Python format string uses multiple unnamed arguments (such as ``%d``). The translator might need to reorder the arguments to properly translate the message, but this is not possible with unnamed arguments. Named arguments (such as ``%(num)d``) should be used instead. References: | https://docs.python.org/2/library/stdtypes.html#string-formatting-operations | https://www.gnu.org/software/gettext/manual/html_node/Python.html#Python Severity, certainty: serious, possible python-format-string-obsolete-conversion ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A Python format string uses an obsolete conversion specifier: * Use ``%d`` instead of ``%u``. References: | https://docs.python.org/2/library/stdtypes.html#string-formatting-operations Severity, certainty: pedantic, possible python-format-string-redundant-flag ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A Python format string includes a redundant character flag. Either it's a duplicate, or it has no effect: * The ``+`` flag overrides the *space* flag. * The ``-`` flag overrides the ``0`` flag. * If a precision is given, the ``0`` flag has no effect on integer conversions (``%d``, ``%i``, ``%o``, ``%u``, ``%x``, and ``%X``). References: | https://docs.python.org/2/library/stdtypes.html#string-formatting-operations Severity, certainty: pedantic, possible python-format-string-redundant-length ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A Python format string includes a redundant length modifier. Length modifiers (``h``, ``l``, or ``L``) have no effect in Python. References: | https://docs.python.org/2/library/stdtypes.html#string-formatting-operations Severity, certainty: pedantic, possible python-format-string-redundant-precision ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A C format string includes precision that has no effect on the conversion. References: | https://docs.python.org/2/library/stdtypes.html#string-formatting-operations Severity, certainty: pedantic, possible python-format-string-unknown-argument ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A Python format string for ``msgid`` uses a named argument that isn't used in ``msgid_plural``; or ``msgstr`` uses a named argument that isn't used in ``msgid``; or ``msgstr[``\ *N*\ ``]`` uses a named argument that isn't used in corresponding ``msgid`` or ``msgid_plural``. This indicates that the conversion would try to consume an argument that weren't supplied. References: | https://docs.python.org/2/library/stdtypes.html#string-formatting-operations | https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: serious, possible python-format-string-unnamed-plural-argument ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A Python format string uses an unnamed arguments (such as ``%d``) in the context of plural forms. The translator might want not to use the numeric argument in the singular form; but this is not possible if the argument is unnamed, because Python, unlike C, requires that all unnamed arguments must be consumed during conversion. Named arguments (such as ``%(n)d``) should be used instead. References: | https://docs.python.org/2/library/stdtypes.html#string-formatting-operations | https://www.gnu.org/software/gettext/manual/html_node/Python.html#Python Severity, certainty: wishlist, possible qt-plural-format-mistaken-for-c-format ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A ``c-format`` flag is associated with the message, but ``qt-plural-format`` should be used instead. The only C format directive that the message uses is ``%n``. It is very atypical to use it alone in a C format string. References: | https://doc.qt.io/qt-5/i18n-source-translation.html#handling-plurals | **printf**\ (3) Severity, certainty: important, possible 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: | https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html Severity, certainty: normal, certain redundant-message-flag ~~~~~~~~~~~~~~~~~~~~~~ A flag associated with one of the messages is redundant, because it's implied by another flag. References: | https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html Severity, certainty: pedantic, certain stray-header-line ~~~~~~~~~~~~~~~~~ The header contains a line that does not belong to any header field. Note that RFC-822-style folding of long headers is not supported. References: | https://lists.gnu.org/archive/html/bug-gettext/2012-12/msg00010.html Severity, certainty: important, certain stray-previous-msgid ~~~~~~~~~~~~~~~~~~~~ The message entry contains annotations about previous untranslated string (``#| msgid``\ *...*), even though the message is not marked as fuzzy. These annotations are only useful for fuzzy messages, and should be removed when unfuzzying. References: | https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html Severity, certainty: minor, 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: | https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: serious, certain 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: | https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html | https://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: | https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Severity, certainty: important, certain trailing-junk-in-plural-forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Plural-Forms header field contains unexpected text after the plural expression. GNU gettext runtime ignores such trailing junk, but other header parsers might be less liberal in what they accept. Severity, certainty: important, certain translation-in-template ~~~~~~~~~~~~~~~~~~~~~~~ The PO template file contains a translated message. Severity, certainty: minor, certain 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: | https://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: | https://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: | https://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: | https://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: | https://www.unicode.org/faq/utf_bom.html#bom6 Severity, certainty: important, possible unusual-plural-forms ~~~~~~~~~~~~~~~~~~~~ The Plural-Forms declaration is incorrect (or unusual), according to i18nspector's linguistic data. Severity, certainty: serious, possible unusual-unused-plural-forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Plural-Forms declaration is incorrect (or unusual), according to i18nspector's linguistic data. (But there are no translated messages which use plural forms.) Severity, certainty: normal, possible i18nspector-0.26/doc/todo0000644000000000000000000001514213733665553015276 0ustar00rootroot00000000000000Add more ``Plural-Forms``. Document how the current ``Plural-Forms`` were obtained. * http://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html?id=l10n/pluralforms * https://unicode.org/cldr/trac/browser/trunk/common/supplemental/plurals.xml Complain about incorrect locale codes: * https://www.loc.gov/standards/iso639-2/php/code_changes.php * ``al`` → ``sq`` * ``bh`` → ``bho`` | ``mai`` | ``mag`` * ``ca-XV`` → ``ca@valencia`` * ``cn`` → ``zh`` * ``cz`` → ``cs`` * ``dk`` → ``da`` * ``en_AM`` → ``en_US`` * ``en_BR`` → ``en_GB`` * ``en_UK`` → ``en_GB`` * ``gr`` → ``el`` * ``in`` → ``id`` * ``iw`` → ``he`` * ``ji`` → ``yi`` * ``jw`` → ``jv`` * ``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``: https://sources.debian.org/data/main/d/debian-handbook/7.20140126~deb7u1/da-DK/00a_preface.po * ``pt_br`` → ``pt_BR``: https://sources.debian.org/data/main/p/pam-pkcs11/0.6.8-1/po/pt_br.po * ``Pt`` → ``pt``: https://sources.debian.org/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)``: https://sources.debian.org/data/main/g/garcon/0.1.12-1/po/nl.po * ``Serbian (sr)``: https://sources.debian.org/data/main/a/at-spi2-atk/2.5.3-2/po/sr.po Guess language from ``Language-Team``. * https://translationproject.org/team/ Guess language from the filename even when it includes encoding. Test-cases: * https://sources.debian.org/src/vim/2:7.3.547-7/src/po/ 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: https://sources.debian.org/src/vim/2:7.3.547-7/src/po/zh_TW.po/#L13 * SHIFT_JIS encoding: https://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 ``--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. 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: * https://sources.debian.org/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: * https://sources.debian.org/data/main/m/mtpaint/3.40-1/po/de.po * https://sources.debian.org/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: * https://sources.debian.org/data/main/a/alarm-clock/1.2.5-1.2/po/sr.po Check for localized boilerplate in headers. Decide what to do with commas in ``Last-Translator``: either accept them, or provide a better error message. Test-case: * https://sources.debian.org/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: * https://marc.info/?l=openbsd-ports&m=98988950322667&w=2 Add support for MediaWiki Translate's ``invalid-plural`` flag. Test-case: * https://sources.debian.org/data/main/e/evolution/3.4.4-3/po/fi.po Add support for pygettext's ``docstring`` flag. Check .desktop files: * https://specifications.freedesktop.org/desktop-entry-spec/latest/ar01s04.html Check Shared Mime Info files: * https://specifications.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: * https://sources.debian.org/src/evolution/3.4.4-3/shell/main.c/#L579 Check for ``msgstr_plural`` without ``msgstr[N]``, and other way round. Verify that if *n* = plural(1) = plural(*i*) for some *i* > 1, then msgstr[*n*] distinguishes singular and plural forms, even when no numeral is involved. * https://bugs.debian.org/753946#51 Add support for more string formats (in order of popularity on GitHub):: php-format javascript-format perl-format java-format csharp-format kde-format sh-format qt-format tcl-format perl-brace-format scheme-format ycp-format lisp-format awk-format objc-format object-pascal-format librep-format smalltalk-format boost-format qt-plural-format lua-format kde-kuit gfc-internal-format gcc-internal-format elisp-format Improve C format string checks: * Check for the ``I`` C format string flag in msgid. * Recognize type mismatch between ``%*d%d`` and ``%d%*d``. * Make sure ``%%`` is treated as text wrt. omitting integer conversion. SHIFT_JIS and JOHAB encodings are broken in Python; or at least they are not compatible with glibc. Implement a work-around. Test-case:: assert b'\\'.decode('SHIFT_JIS') == '\N{YEN SIGN}' assert b'\\'.decode('JOHAB') == '\N{WON SIGN}' Timezone abbreviations not only are not unique, but also can change their meaning over time. * https://mm.icann.org/pipermail/tz/2014-June/021089.html Check for capitalization inconsistencies. Language codes for some locales supported by glibc aren't recognized:: ayc ber brx cmn hak hne lij lzh mhr nan nhn pap quz shs szl the unm wae yue The tag name ``invalid-language`` might be misleading. Rename or split it. Check for ``li.org`` mailing lists in ``Language-Team``. * https://lists.gnu.org/archive/html/bug-gettext/2016-02/msg00003.html Add support for xgettext message syntax check flags: * https://git.savannah.gnu.org/cgit/gettext.git/commit/?id=d9fc3d2a3f43 .. vim:ft=rst ts=3 sts=3 sw=3 i18nspector-0.26/i18nspector0000755000000000000000000000537513733665553015755 0ustar00rootroot00000000000000#!/usr/bin/env python3 # encoding=UTF-8 # Copyright © 2012-2019 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 # pylint: disable=import-outside-toplevel ap = argparse.ArgumentParser() prog = ap.prog except ImportError: import optparse # pylint: disable=deprecated-module,import-outside-toplevel 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) def require_polib(*version): import polib # pylint: disable=import-outside-toplevel polib_version = tuple( int(x) for x in polib.__version__.split('.') ) if polib_version < version: version_str = '.'.join(map(str, version)) message = 'polib >= {ver} is required'.format(ver=version_str) error(message) require_python(3, 4) require_polib(1, 0, 0) # ---------------------------------------- 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] # pylint: disable=wrong-import-position 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 sts=4 sw=4 et i18nspector-0.26/lib/0000755000000000000000000000000013733665556014407 5ustar00rootroot00000000000000i18nspector-0.26/lib/__init__.py0000644000000000000000000000011413733665553016511 0ustar00rootroot00000000000000''' i18nspector's private modules ''' type(...) # Python >= 3 is required i18nspector-0.26/lib/check/0000755000000000000000000000000013733665553015461 5ustar00rootroot00000000000000i18nspector-0.26/lib/check/__init__.py0000644000000000000000000013271013733665553017576 0ustar00rootroot00000000000000# Copyright © 2012-2018 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 heapq import os import re import types import urllib.parse import polib from lib import domains from lib import encodings as encinfo from lib import gettext from lib import ling from lib import misc from lib import polib4us from lib import tags from lib import xml from lib.check.msgformat import c as msgformat_c from lib.check.msgformat import perlbrace as msgformat_perlbrace from lib.check.msgformat import pybrace as msgformat_pybrace from lib.check.msgformat import python as msgformat_python from lib.check.msgrepr import message_repr 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(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 self._message_format_checkers = { 'c': msgformat_c.Checker(self), 'perl-brace': msgformat_perlbrace.Checker(self), 'python': msgformat_python.Checker(self), 'python-brace': msgformat_pybrace.Checker(self), } @abc.abstractmethod def tag(self, tagname, *extra): pass 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 OSError as exc: self.tag('os-error', tags.safestr(exc.strerror)) return if self.options.file_type is None: extension = os.path.splitext(self.path)[-1] else: extension = '.' + self.options.file_type is_template = False is_binary = False if extension == '.po': constructor = polib.pofile elif extension == '.pot': constructor = polib.pofile is_template = True elif extension in ('.mo', '.gmo'): constructor = polib.mofile is_binary = True 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 OSError as exc: message = str(exc) if exc.errno is not None: self.tag('os-error', tags.safestr(exc.strerror)) 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: # pylint: disable=no-member 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(), ) # pylint: enable=no-member broken_encoding = True ctx = types.SimpleNamespace() ctx.file = file ctx.is_template = is_template ctx.is_binary = is_binary self.check_comments(ctx) self.check_headers(ctx) self.check_language(ctx) self.check_plurals(ctx) self.check_mime(ctx) if broken_encoding: ctx.encoding = None self.check_dates(ctx) self.check_project(ctx) self.check_translator(ctx) self.check_messages(ctx) def check_comments(self, ctx): regexs = { r'\bPACKAGE package\b', r'\bCopyright \S+ YEAR\b', r"\bTHE PACKAGE'S COPYRIGHT HOLDER\b", } if not ctx.is_template: regexs |= { r'\bFIRST AUTHOR\b', r'', r'(?<=>), YEAR\b', } regex = re.compile('|'.join(regexs)) for line in ctx.file.header.splitlines(): match = regex.search(line) if match is None: continue self.tag('boilerplate-in-initial-comments', line) @checks_header_fields('Language', 'X-Poedit-Language', 'X-Poedit-Country') def check_language(self, ctx): ctx.language = None duplicate_meta_language = False meta_languages = ctx.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 ctx.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 = ctx.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 = ctx.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) ctx.language = language @checks_header_fields('Plural-Forms') def check_plurals(self, ctx): ctx.plural_preimage = None plural_forms = ctx.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 ctx.language is not None: correct_plural_forms = ctx.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 ctx.file: if message.obsolete: continue if message.msgid_plural is not None: 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 ctx.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 ctx.is_template: return try: (n, expr, ljunk, rjunk) = gettext.parse_plural_forms(plural_forms, strict=False) 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) return if ljunk: self.tag('leading-junk-in-plural-forms', ljunk) if rjunk: self.tag('trailing-junk-in-plural-forms', rjunk) 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('unusual-plural-forms', plural_forms, '=>', plural_forms_hint) else: self.tag('unusual-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 plural_preimage = collections.defaultdict(list) unusual_plural_forms = False codomain_limit = 200 try: for i in range(codomain_limit): 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 plural_preimage[fi] += [i] if (n == locally_correct_n) and (fi != locally_correct_expr(i)) and (not unusual_plural_forms): if has_plurals: self.tag('unusual-plural-forms', plural_forms, '=>', plural_forms_hint) else: self.tag('unusual-unused-plural-forms', plural_forms, '=>', plural_forms_hint) unusual_plural_forms = True else: ctx.plural_preimage = dict(plural_preimage) 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 uncov_rngs = [] if x > 0: uncov_rngs += [range(0, x)] if y + 1 < n: uncov_rngs += [range(y + 1, n)] if (not uncov_rngs) and (ctx.plural_preimage is not None): period = expr.period() if period is None: period = (0, 1e999) if sum(period) < codomain_limit: for i in sorted(ctx.plural_preimage): if (i > 0) and (i - 1 not in ctx.plural_preimage): uncov_rngs += [range(i - 1, i)] break if (i + 1 < n) and (i + 1 not in ctx.plural_preimage): uncov_rngs += [range(i + 1, i + 2)] break for rng in uncov_rngs: 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) ctx.plural_preimage = None @checks_header_fields('MIME-Version', 'Content-Transfer-Encoding', 'Content-Type') def check_mime(self, ctx): ctx.encoding = None # MIME-Version: mime_versions = ctx.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 = ctx.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 = ctx.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 ctx.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 ctx.language is not None: unrepresentable_characters = ctx.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: [ctx.encoding] = encodings @checks_header_fields('POT-Creation-Date', 'PO-Revision-Date') def check_dates(self, ctx): try: content_type = ctx.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 = ctx.metadata[field] if len(dates) > 1: self.tag('duplicate-header-field-date', field) dates = sorted(set(dates)) elif len(dates) == 0: if field.startswith('POT-') and ctx.is_binary: # In gettext >> 0.19.8.1, msgfmt will be removing # the POT-Creation-Date header. # https://savannah.gnu.org/bugs/?49654 continue self.tag('no-date-header-field', field) continue for date in dates: if ctx.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: # https://sources.debian.org/src/publican/2.8-3/lib/Publican/Translate.pm/?hl=748#L744 # https://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, ctx): # Project-Id-Version: project_id_versions = ctx.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.search(r'[^_\d\W]', 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 = ctx.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) del real_name 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) elif domains.is_email_in_dotless_domain(email_address): self.tag('invalid-report-msgid-bugs-to', report_msgid_bugs_to) @checks_header_fields('Last-Translator', 'Language-Team') def check_translator(self, ctx): # Last-Translator: translators = ctx.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 = {} for translator in translators: translator_name, translator_email = email.utils.parseaddr(translator) del translator_name translator_emails[translator_email] = translator 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 ctx.is_template: self.tag('boilerplate-in-last-translator', translator) elif domains.is_email_in_dotless_domain(translator_email): self.tag('invalid-last-translator', translator) # Language-Team: teams = ctx.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) del team_name if '@' not in team_email: # TODO: A 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 ctx.is_template: self.tag('boilerplate-in-language-team', team) elif domains.is_email_in_dotless_domain(team_email): self.tag('invalid-language-team', team) else: translator = translator_emails.get(team_email) if translator is not None: self.tag('language-team-equal-to-last-translator', team, translator) def check_headers(self, ctx): metadata = collections.defaultdict(list) strays = [] ctx.file.header_entry = None seen_header_entry = False for entry in ctx.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 is not None: self.tag('empty-msgid-message-with-plural-forms') msgstr = entry.msgstr_plural.get(0, entry.msgstr) # At least in polib 1.0.0, if the source PO file is empty, # msgstr for the header entry is None. msgstr = msgstr or '' for line in gettext.parse_header(msgstr): if isinstance(line, dict): [(key, value)] = line.items() metadata[key] += [value] else: strays += [line] flags = collections.Counter(entry.flags) for flag, n in sorted(flags.items()): if flag == 'fuzzy': if not ctx.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 ctx.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 key.startswith(('X-', 'x-')): pass # ok elif key in header_fields: pass # ok else: 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) ctx.metadata = metadata del ctx.file.metadata del ctx.file.metadata_is_fuzzy def check_messages(self, ctx): found_unusual_characters = set() msgid_counter = collections.Counter() for message in ctx.file: if message.obsolete: continue if is_header_entry(message): continue flags = self._check_message_flags(message) self._check_message_formats(ctx, message, flags) msgid_counter[message.msgid, message.msgctxt] += 1 if msgid_counter[message.msgid, message.msgctxt] == 2: self.tag('duplicate-message-definition', message_repr(message)) has_msgstr = bool(message.msgstr) has_msgstr_plural = any(message.msgstr_plural.values()) if ctx.is_template: if has_msgstr or has_msgstr_plural: self.tag('translation-in-template', message_repr(message)) leading_lf = message.msgid.startswith('\n') trailing_lf = message.msgid.endswith('\n') has_previous_msgid = any(s is not None for s in [ message.previous_msgctxt, message.previous_msgid, message.previous_msgid_plural, ]) if has_previous_msgid and not flags.fuzzy: self.tag('stray-previous-msgid', message_repr(message)) strings = [] if message.msgid_plural is not None: strings += [message.msgid_plural] if not flags.fuzzy: if has_msgstr: strings += [message.msgstr] if has_msgstr_plural: strings += message.msgstr_plural.values() # the order doesn't matter here 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 strings = [] if has_msgstr: strings += [message.msgstr] if has_msgstr_plural: strings += misc.sorted_vk(message.msgstr_plural) if ctx.encoding is not None: msgid_uc = ( set(find_unusual_characters(message.msgid)) | set(find_unusual_characters(message.msgid_plural or '')) ) for msgstr in strings: msgstr_uc = set(find_unusual_characters(msgstr)) uc = msgstr_uc - msgid_uc - found_unusual_characters if not uc: continue names = ', '.join( 'U+{:04X} {}'.format(ord(ch), encinfo.get_character_name(ch)) for ch in sorted(uc) ) self.tag('unusual-character-in-translation', message_repr(message, template='{}:'), tags.safestr(names) ) found_unusual_characters |= uc if not flags.fuzzy: for msgstr in strings: 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) break if has_msgstr_plural and not all(message.msgstr_plural.values()): self.tag('partially-translated-message', message_repr(message)) if len(msgid_counter) == 0: possible_hidden_strings = False if ctx.is_binary: possible_hidden_strings = ctx.file.possible_hidden_strings if not possible_hidden_strings: self.tag('empty-file') def _check_message_flags(self, message): info = types.SimpleNamespace() info.fuzzy = False info.range_min = 0 info.range_max = 1e999 # +inf info.formats = None flags = collections.Counter(message.flags) wrap = None format_flags = collections.defaultdict(dict) range_flags = collections.defaultdict( collections.Counter ) for flag, n in sorted(flags.items()): known_flag = True if flag == 'fuzzy': info.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 message.msgid_plural is None: self.tag('range-flag-without-plural-string') match = re.match(r'\A([0-9]+)[.][.]([0-9]+)\Z', flag[6:].strip(' \t\r\f\v')) if match is not None: i, j = map(int, match.groups()) if i < j: info.range_min = i info.range_max = j else: match = None if match is None: self.tag('invalid-range-flag', message_repr(message, template='{}:'), flag ) else: range_flags[i, j][flag] += n n = 0 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 ) if len(range_flags) > 1: [range1, range2] = heapq.nsmallest(2, range_flags.keys()) self.tag('conflicting-message-flags', message_repr(message, template='{}:'), min(range_flags[range1].keys()), min(range_flags[range2].keys()), ) elif len(range_flags) == 1: [range_flags] = range_flags.values() if sum(range_flags.values()) > 1: self.tag('duplicate-message-flag', message_repr(message, template='{}:'), min(range_flags.keys()) ) positive_format_flags = format_flags[''] info.formats = frozenset(positive_format_flags) for fmt1, flag1 in sorted(positive_format_flags.items()): for fmt2, flag2 in sorted(positive_format_flags.items()): if fmt1 >= fmt2: continue fmt_ex1 = gettext.string_formats[fmt1] fmt_ex2 = gettext.string_formats[fmt2] if fmt_ex1 & fmt_ex2: # the formats are, at least to some extent, compatible continue self.tag('conflicting-message-flags', message_repr(message, template='{}:'), flag1, flag2 ) 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])) ) return info def _check_message_formats(self, ctx, message, flags): for fmt in sorted(flags.formats): try: checker = self._message_format_checkers[fmt] except KeyError: continue checker.check_message(ctx, message, flags) if re.match(r'\Atype: Content of: (<{xmlname}>)+\Z'.format(xmlname=xml.name_re), message.comment or ''): self._check_message_xml_format(ctx, message, flags) def _check_message_xml_format(self, ctx, message, flags): if ctx.encoding is None: return prefix = message_repr(message, template='{}:') try: xml.check_fragment(message.msgid) except xml.SyntaxError as exc: if ctx.is_template: self.tag('malformed-xml', prefix, tags.safestr(exc)) return if flags.fuzzy: return if not message.msgstr: return try: xml.check_fragment(message.msgstr) except xml.SyntaxError as exc: self.tag('malformed-xml', prefix, tags.safestr(exc)) __all__ = ['Checker'] def is_header_entry(entry): return ( entry.msgid == '' and entry.msgctxt is None ) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/check/msgformat/0000755000000000000000000000000013733665553017460 5ustar00rootroot00000000000000i18nspector-0.26/lib/check/msgformat/__init__.py0000644000000000000000000001544713733665553021604 0ustar00rootroot00000000000000# Copyright © 2014-2017 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. ''' message format checks ''' import abc import types class Checker(metaclass=abc.ABCMeta): def __init__(self, parent): self.parent = parent @abc.abstractproperty def backend(self): pass def tag(self, tagname, *extra): return self.parent.tag(tagname, *extra) def check_message(self, ctx, message, flags): msgids = [message.msgid] if message.msgid_plural is not None: msgids += [message.msgid_plural] msgid_fmts = {} for i, s in enumerate(msgids): if ctx.is_template: fmt = self.check_string(ctx, message, s) else: try: fmt = self.backend.FormatString(s) except self.backend.Error: # If msgid isn't even a valid format string, then # reporting errors against msgstr is not worth the trouble. return if fmt is not None: msgid_fmts[i] = fmt if ctx.is_template and (len(msgid_fmts) == 2): self.check_args( message, 'msgid_plural', msgid_fmts[1], 'msgid', msgid_fmts[0], omitted_int_conv_ok=True, ) self.check_msgids(message, msgid_fmts) if flags.fuzzy: return if ctx.encoding is None: return has_msgstr = bool(message.msgstr) has_msgstr_plural = any(message.msgstr_plural.values()) strings = [] if has_msgstr: d = types.SimpleNamespace() d.src_loc = 'msgid' d.src_fmt = msgid_fmts.get(0) d.dst_loc = 'msgstr' d.dst_fmt = self.check_string(ctx, message, message.msgstr) d.omitted_int_conv_ok = False strings += [d] if has_msgstr_plural and ctx.plural_preimage: for i, s in sorted(message.msgstr_plural.items()): assert isinstance(i, int) d = types.SimpleNamespace() msgid_fmt = msgid_fmts.get(0) msgid_plural_fmt = msgid_fmts.get(1) d.src_loc = 'msgid_plural' d.src_fmt = msgid_plural_fmt d.dst_loc = 'msgstr[{}]'.format(i) d.dst_fmt = self.check_string(ctx, message, s) if d.dst_fmt is None: continue try: preimage = ctx.plural_preimage[i] except KeyError: # broken plural forms continue preimage = [ x for x in preimage if flags.range_min <= x <= flags.range_max ] # XXX In theory, the msgstr[] corresponding to n=1 should # not have more arguments than msgid. In practice, it's not # uncommon to see something like this: # # 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; # # msgid "one byte" # msgid_plural "%d bytes" # msgstr[0] "%d bajt" # msgstr[1] "%d bajta" # msgstr[2] "%d bajtova" # # Here %d in msgstr[0] cannot be omitted, because it is used # not only for n=1, but also for n=21, n=31, and so on. # # To be pedantically correct, one could use a different # Plural-Forms, such that there is a separate value for n=1. # # See also: https://bugs.debian.org/753946 if preimage == [1]: # FIXME: “preimage” is not necessarily complete. # So it's theoretically possible that this msgstr[] # corresponds to both n=1 and another n. d.src_loc = 'msgid' d.src_fmt = msgid_fmt d.omitted_int_conv_ok = ( msgid_fmt is not None and msgid_plural_fmt is not None and len(msgid_fmt) == len(msgid_plural_fmt) # FIXME: The length equality is a rather weak indicator # that msgid and msgid_plural are equivalent. ) elif len(preimage) <= 1: d.omitted_int_conv_ok = True elif len(preimage) == 2 and preimage[0] == 0: # XXX In theory, the integer conversion should not be # omitted in the msgstr[] corresponding to both n=0 and # another n. In practice, it's sometimes obvious from # context that the message will never be used for n=0. d.omitted_int_conv_ok = True else: d.omitted_int_conv_ok = False strings += [d] for d in strings: if d.dst_fmt is None: continue if d.src_fmt is None: continue assert d.src_loc is not None assert d.dst_loc is not None self.check_args(message, d.src_loc, d.src_fmt, d.dst_loc, d.dst_fmt, omitted_int_conv_ok=d.omitted_int_conv_ok, ) def check_msgids(self, message, msgid_fmts): pass # no coverage @abc.abstractmethod def check_string(self, ctx, message, s): pass # no coverage @abc.abstractmethod def check_args(self, message, src_loc, src_fmt, dst_loc, dst_fmt, *, omitted_int_conv_ok=False): pass # no coverage __all__ = ['Checker'] # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/check/msgformat/c.py0000644000000000000000000001272713733665553020265 0ustar00rootroot00000000000000# Copyright © 2014-2017 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. ''' message format checks: C ''' from lib import tags from lib.check.msgformat import Checker as CheckerBase from lib.check.msgrepr import message_repr from lib.strformat import c as backend class Checker(CheckerBase): backend = backend # pylint: disable=self-assigning-variable def check_msgids(self, message, msgid_fmts): if msgid_fmts.get(0) is not None: try: [[arg]] = msgid_fmts[0].arguments except ValueError: pass else: if arg.type == 'int *': self.tag('qt-plural-format-mistaken-for-c-format', message_repr(message)) def check_string(self, ctx, message, s): prefix = message_repr(message, template='{}:') fmt = None try: fmt = backend.FormatString(s) except backend.MissingArgument as exc: self.tag('c-format-string-error', prefix, tags.safestr(exc.message), tags.safestr('{1}$'.format(*exc.args)), ) except backend.ArgumentTypeMismatch as exc: self.tag('c-format-string-error', prefix, tags.safestr(exc.message), tags.safestr('{1}$'.format(*exc.args)), tags.safestr(', '.join(sorted(x for x in exc.args[2]))), ) except backend.FlagError as exc: [conv, flag] = exc.args # pylint: disable=unbalanced-tuple-unpacking self.tag('c-format-string-error', prefix, tags.safestr(exc.message), flag, tags.safestr('in'), conv ) except backend.Error as exc: self.tag('c-format-string-error', prefix, tags.safestr(exc.message), *exc.args[:1] ) if fmt is None: return for warn in fmt.warnings: try: raise warn except backend.RedundantFlag as exc: if len(exc.args) == 2: [s, *args] = exc.args else: [s, a1, a2] = exc.args # pylint: disable=unbalanced-tuple-unpacking if a1 == a2: args = ['duplicate', a1] else: args = [a1, tags.safe_format('overridden by {}', a2)] args += ['in', s] self.tag('c-format-string-redundant-flag', prefix, *args ) except backend.NonPortableConversion as exc: [s, c1, c2] = exc.args # pylint: disable=unbalanced-tuple-unpacking args = [c1, '=>', c2] if s != c1: args += ['in', s] self.tag('c-format-string-non-portable-conversion', prefix, *args ) return fmt def check_args(self, message, src_loc, src_fmt, dst_loc, dst_fmt, *, omitted_int_conv_ok=False): prefix = message_repr(message, template='{}:') src_args = src_fmt.arguments dst_args = dst_fmt.arguments if len(dst_args) > len(src_args): self.tag('c-format-string-excess-arguments', prefix, len(dst_args), tags.safestr('({})'.format(dst_loc)), '>', len(src_args), tags.safestr('({})'.format(src_loc)), ) elif len(dst_args) < len(src_args): if omitted_int_conv_ok: n_args_omitted = len(src_args) - len(dst_args) omitted_int_conv_ok = src_fmt.get_last_integer_conversion(n=n_args_omitted) if not omitted_int_conv_ok: self.tag('c-format-string-missing-arguments', prefix, len(dst_args), tags.safestr('({})'.format(dst_loc)), '<', len(src_args), tags.safestr('({})'.format(src_loc)), ) for src_arg, dst_arg in zip(src_args, dst_args): src_arg = src_arg[0] dst_arg = dst_arg[0] if src_arg.type != dst_arg.type: self.tag('c-format-string-argument-type-mismatch', prefix, tags.safestr(dst_arg.type), tags.safestr('({})'.format(dst_loc)), '!=', tags.safestr(src_arg.type), tags.safestr('({})'.format(src_loc)), ) __all__ = ['Checker'] # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/check/msgformat/perlbrace.py0000644000000000000000000000545713733665553022004 0ustar00rootroot00000000000000# Copyright © 2016-2020 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. ''' message format checks: Perl Locale::TextDomain ''' from lib import tags from lib.check.msgformat import Checker as CheckerBase from lib.check.msgrepr import message_repr from lib.strformat import perlbrace as backend class Checker(CheckerBase): backend = backend # pylint: disable=self-assigning-variable def check_string(self, ctx, message, s): prefix = message_repr(message, template='{}:') fmt = None try: fmt = backend.FormatString(s) except backend.Error as exc: self.tag('perl-brace-format-string-error', prefix, tags.safestr(exc.message), *exc.args[:1] ) else: return fmt def check_args(self, message, src_loc, src_fmt, dst_loc, dst_fmt, *, omitted_int_conv_ok=False): def sort_key(item): return (isinstance(item, str), item) prefix = message_repr(message, template='{}:') src_args = src_fmt.arguments dst_args = dst_fmt.arguments for key in sorted(dst_args - src_args, key=sort_key): self.tag('perl-brace-format-string-unknown-argument', prefix, key, tags.safestr('in'), tags.safestr(dst_loc), tags.safestr('but not in'), tags.safestr(src_loc), ) missing_keys = src_args - dst_args if len(missing_keys) == 1 and omitted_int_conv_ok: missing_keys = () for key in sorted(missing_keys): self.tag('perl-brace-format-string-missing-argument', prefix, key, tags.safestr('not in'), tags.safestr(dst_loc), tags.safestr('while in'), tags.safestr(src_loc), ) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/check/msgformat/pybrace.py0000644000000000000000000000671413733665553021467 0ustar00rootroot00000000000000# Copyright © 2016-2017 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. ''' message format checks: Python's str.format() ''' from lib import tags from lib.check.msgformat import Checker as CheckerBase from lib.check.msgrepr import message_repr from lib.strformat import pybrace as backend class Checker(CheckerBase): backend = backend # pylint: disable=self-assigning-variable def check_string(self, ctx, message, s): prefix = message_repr(message, template='{}:') fmt = None try: fmt = backend.FormatString(s) except backend.Error as exc: self.tag('python-brace-format-string-error', prefix, tags.safestr(exc.message), *exc.args[:1] ) else: return fmt def check_args(self, message, src_loc, src_fmt, dst_loc, dst_fmt, *, omitted_int_conv_ok=False): def sort_key(item): return (isinstance(item, str), item) prefix = message_repr(message, template='{}:') src_args = src_fmt.argument_map dst_args = dst_fmt.argument_map for key in sorted(dst_args.keys() & src_args.keys(), key=sort_key): src_arg = src_args[key][0] dst_arg = dst_args[key][0] if not (src_arg.types & dst_arg.types): self.tag('python-brace-format-string-argument-type-mismatch', prefix, tags.safestr(', '.join(dst_arg.types)), tags.safestr('({})'.format(dst_loc)), '!=', tags.safestr(', '.join(src_arg.types)), tags.safestr('({})'.format(src_loc)), ) for key in sorted(dst_args.keys() - src_args.keys(), key=sort_key): self.tag('python-brace-format-string-unknown-argument', prefix, key, tags.safestr('in'), tags.safestr(dst_loc), tags.safestr('but not in'), tags.safestr(src_loc), ) missing_keys = src_args.keys() - dst_args.keys() if len(missing_keys) == 1 and omitted_int_conv_ok: [missing_key] = missing_keys if all('int' in arg.types for arg in src_args[missing_key]): missing_keys = set() for key in sorted(missing_keys): self.tag('python-brace-format-string-missing-argument', prefix, key, tags.safestr('not in'), tags.safestr(dst_loc), tags.safestr('while in'), tags.safestr(src_loc), ) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/check/msgformat/python.py0000644000000000000000000001521613733665553021360 0ustar00rootroot00000000000000# Copyright © 2015 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. ''' message format checks: Python's %-formatting ''' from lib import tags from lib.check.msgformat import Checker as CheckerBase from lib.check.msgrepr import message_repr from lib.strformat import python as backend class Checker(CheckerBase): backend = backend # pylint: disable=self-assigning-variable def check_string(self, ctx, message, s): prefix = message_repr(message, template='{}:') fmt = None try: fmt = backend.FormatString(s) except backend.ArgumentTypeMismatch as exc: [s, key, types] = exc.args # pylint: disable=unbalanced-tuple-unpacking self.tag('python-format-string-error', prefix, tags.safestr(exc.message), tags.safestr(key), tags.safestr(', '.join(sorted(x for x in types))), ) except backend.Error as exc: self.tag('python-format-string-error', prefix, tags.safestr(exc.message), *exc.args[:1] ) if fmt is None: return for warn in fmt.warnings: try: raise warn except backend.RedundantFlag as exc: if len(exc.args) == 2: [s, *args] = exc.args else: [s, a1, a2] = exc.args # pylint: disable=unbalanced-tuple-unpacking if a1 == a2: args = ['duplicate', a1] else: args = [a1, tags.safe_format('overridden by {}', a2)] args += ['in', s] self.tag('python-format-string-redundant-flag', prefix, *args ) except backend.RedundantPrecision as exc: [s, a] = exc.args # pylint: disable=unbalanced-tuple-unpacking self.tag('python-format-string-redundant-precision', prefix, a, 'in', s ) except backend.RedundantLength as exc: [s, a] = exc.args # pylint: disable=unbalanced-tuple-unpacking self.tag('python-format-string-redundant-length', prefix, a, 'in', s ) except backend.ObsoleteConversion as exc: [s, c1, c2] = exc.args # pylint: disable=unbalanced-tuple-unpacking args = [c1, '=>', c2] if s != c1: args += ['in', s] self.tag('python-format-string-obsolete-conversion', prefix, *args ) if ctx.is_template: if len(fmt.seq_conversions) > 1: self.tag('python-format-string-multiple-unnamed-arguments', message_repr(message) ) elif len(fmt.seq_conversions) == 1: arg_for_plural = ( message.msgid_plural is not None and fmt.seq_conversions[0].type == 'int' ) if arg_for_plural: self.tag('python-format-string-unnamed-plural-argument', message_repr(message) ) return fmt def check_args(self, message, src_loc, src_fmt, dst_loc, dst_fmt, *, omitted_int_conv_ok=False): prefix = message_repr(message, template='{}:') # unnamed arguments: src_args = src_fmt.seq_arguments dst_args = dst_fmt.seq_arguments if len(dst_args) != len(src_args): self.tag('python-format-string-argument-number-mismatch', prefix, len(dst_args), tags.safestr('({})'.format(dst_loc)), '!=', len(src_args), tags.safestr('({})'.format(src_loc)), ) for src_arg, dst_arg in zip(src_args, dst_args): if src_arg.type != dst_arg.type: self.tag('python-format-string-argument-type-mismatch', prefix, tags.safestr(dst_arg.type), tags.safestr('({})'.format(dst_loc)), '!=', tags.safestr(src_arg.type), tags.safestr('({})'.format(src_loc)), ) # named arguments: src_args = src_fmt.map_arguments dst_args = dst_fmt.map_arguments for key in sorted(dst_args.keys() & src_args.keys()): src_arg = src_args[key][0] dst_arg = dst_args[key][0] if src_arg.type != dst_arg.type: self.tag('python-format-string-argument-type-mismatch', prefix, tags.safestr(dst_arg.type), tags.safestr('({})'.format(dst_loc)), '!=', tags.safestr(src_arg.type), tags.safestr('({})'.format(src_loc)), ) for key in sorted(dst_args.keys() - src_args.keys()): self.tag('python-format-string-unknown-argument', prefix, key, tags.safestr('in'), tags.safestr(dst_loc), tags.safestr('but not in'), tags.safestr(src_loc), ) missing_keys = src_args.keys() - dst_args.keys() if len(missing_keys) == 1 and omitted_int_conv_ok: [missing_key] = missing_keys if all(arg.type == 'int' for arg in src_args[missing_key]): missing_keys = set() for key in sorted(missing_keys): self.tag('python-format-string-missing-argument', prefix, key, tags.safestr('not in'), tags.safestr(dst_loc), tags.safestr('while in'), tags.safestr(src_loc), ) __all__ = ['Checker'] # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/check/msgrepr.py0000644000000000000000000000303113733665553017507 0ustar00rootroot00000000000000# Copyright © 2012-2016 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 representation of messages ''' from lib import tags 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) __all__ = ['message_repr'] # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/cli.py0000644000000000000000000001777613733665553015547 0ustar00rootroot00000000000000# Copyright © 2012-2020 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 concurrent.futures import functools import io import multiprocessing import os import subprocess as ipc import sys import tempfile from lib import check from lib import ling from lib import misc from lib import paths as pathmod from lib import tags from lib import terminal __version__ = '0.26' 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', line_buffering=sys.stdout.line_buffering, ) class Checker(check.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_regular_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 ignore_tags = set(options.ignore_tags) ignore_tags.add('unknown-file-type') with tempfile.TemporaryDirectory(prefix='i18nspector.deb.') as tmpdir: if binary: ipc.check_call(['dpkg-deb', '-x', filename, tmpdir]) real_root = os.path.join(tmpdir, '') else: real_root = os.path.join(tmpdir, 's', '') ipc.check_call( ['dpkg-source', '--no-copy', '--no-check', '-x', filename, real_root], stdout=ipc.DEVNULL # 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): del dirs 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) def check_file(path, *, options): if options.unpack_deb: try: return check_deb(path, options=options) except UnsupportedFileType: pass return check_regular_file(path, options=options) def check_file_s(path, *, options): ''' check_file() with captured stdout ''' orig_stdout = sys.stdout sys.stdout = io_stdout = io.StringIO() try: check_file(path, options=options) finally: sys.stdout = orig_stdout return io_stdout.getvalue() def check_all(paths, *, options): if (len(paths) <= 1) or (options.jobs <= 1): for path in paths: check_file(path, options=options) else: executor = concurrent.futures.ProcessPoolExecutor(max_workers=options.jobs) with executor: check_file_opt = functools.partial(check_file_s, options=options) for s in executor.map(check_file_opt, paths): sys.stdout.write(s) def parse_jobs(s): if s == 'auto': try: return multiprocessing.cpu_count() except NotImplementedError: return 1 n = int(s) if n <= 0: raise ValueError return n parse_jobs.__name__ = 'jobs' class VersionAction(argparse.Action): def __init__(self, option_strings, dest=argparse.SUPPRESS): super().__init__( option_strings=option_strings, dest=dest, nargs=0, help='show version information and exit' ) @staticmethod def _get_rply_version(): rply = check.gettext.intexpr.rply try: return rply.__version__ except AttributeError: # __version__ is available only since rply 0.7.5: # https://github.com/alex/rply/pull/58 pass if sys.version_info >= (3, 8): import importlib.metadata # pylint: disable=import-outside-toplevel,import-error,no-name-in-module return importlib.metadata.version('rply') # pylint: disable=no-member try: import pkg_resources # pylint: disable=import-outside-toplevel [dist, *rest] = pkg_resources.require('rply') del rest except ImportError: # oh well... return assert dist.project_name == 'rply' return dist.version def __call__(self, parser, namespace, values, option_string=None): print('{prog} {0}'.format(__version__, prog=parser.prog)) print('+ Python {0}.{1}.{2}'.format(*sys.version_info)) print('+ polib {0}'.format(check.polib.__version__)) rply_version = self._get_rply_version() if rply_version is not None: print('+ rply {0}'.format(rply_version)) parser.exit() def main(): initialize_terminal() ap = argparse.ArgumentParser(description=__doc__) ap.add_argument('--version', action=VersionAction) ap.add_argument('-l', '--language', metavar='', help='assume this language') ap.add_argument('--unpack-deb', action='store_true', help='allow unpacking Debian packages') ap.add_argument('-j', '--jobs', type=parse_jobs, metavar='', default=None, help='use processes') ap.add_argument('--parallel', type=int, metavar='', default=None, help=argparse.SUPPRESS) # renamed as -j/--jobs in 0.25 ap.add_argument('--file-type', metavar='', help=argparse.SUPPRESS) 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 pathmod.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 if options.jobs is None: if options.parallel is not None: options.jobs = options.parallel if options.jobs is None: options.jobs = 1 del options.parallel options.ignore_tags = set() options.fake_root = None Checker.patch_environment() check_all(files, options=options) __all__ = ['main'] # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/domains.py0000644000000000000000000000456113733665553016416 0ustar00rootroot00000000000000# Copyright © 2013-2016 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 ''' # https://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) def is_dotless_domain(domain): return '.' not in domain def is_email_in_dotless_domain(email): # Technically, e-mail addresses in dotless domains are not forbidden. # But in practice they are almost certainly mistakes. # See also: RFC 7085 _, domain = email.rsplit('@', 1) return is_dotless_domain(domain) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/encodings.py0000644000000000000000000001744713733665553016744 0ustar00rootroot00000000000000# Copyright © 2012-2020 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 functools import itertools import os import unicodedata import sys from lib import iconv from lib import misc from lib import paths class EncodingLookupError(LookupError): def __init__(self, encoding): LookupError.__init__(self, 'unknown encoding: ' + encoding) def _not_implemented(*args, **kwargs): # no coverage del 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 FileNotFoundError: raise EncodingLookupError(encoding) 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() _unmangle_encoding = {} if sys.version_info >= (3, 9): # Python >= 3.9 replaces hyphens with underscores: # https://bugs.python.org/issue39337 # We need to undo this damage. for _key in set(_portable_encodings) | set(_extra_encodings): assert _key not in _unmangle_encoding _unmangle_encoding[_key.replace('-', '_')] = _key _key = None del _key 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): del python # 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: decoded_ascii_bytes = _interesting_ascii_bytes.decode(encoding) if isinstance(decoded_ascii_bytes, bytes): # may happen on PyPy for non-text encodings raise RuntimeError return decoded_ascii_bytes == _interesting_ascii_str except UnicodeDecodeError: return False except LookupError: pass except Exception: # no coverage; pylint: disable=broad-except pass if missing_ok: return False else: raise EncodingLookupError(encoding) def _codec_search_function(encoding): encoding = _unmangle_encoding.get(encoding, 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 sts=4 sw=4 et i18nspector-0.26/lib/gettext.py0000644000000000000000000001417513733665553016452 0ustar00rootroot00000000000000# Copyright © 2012-2018 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 os import re from lib import intexpr from lib import misc from lib 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 # https://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 # https://git.savannah.gnu.org/cgit/gettext.git/tree/gettext-tools/src/msgl-cat.c?id=v0.18.3#n590 # https://www.gnu.org/software/gettext/manual/html_node/Creating-Compendia.html#Creating-Compendia # ============ # plural forms # ============ class PluralFormsSyntaxError(Exception): pass class PluralExpressionSyntaxError(PluralFormsSyntaxError): pass def parse_plural_expression(s): parser = intexpr.Parser() try: return parser.parse(s) except intexpr.LexingError: raise PluralExpressionSyntaxError except intexpr.ParsingError: raise PluralExpressionSyntaxError _parse_plural_forms = re.compile(r'nplurals=([1-9][0-9]*);[ \t]*plural=([^;]+);?').search def parse_plural_forms(s, strict=True): match = _parse_plural_forms(s) if match is None: raise PluralFormsSyntaxError n = int(match.group(1), 10) expr = parse_plural_expression(match.group(2)) if strict: if match.start() != 0: raise PluralFormsSyntaxError if match.end() != len(s): raise PluralFormsSyntaxError return (n, expr) else: ljunk = s[:match.start()] rjunk = s[match.end():] return (n, expr, ljunk, rjunk) # ===== # 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(r''' ^ ( [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(r''' ^ 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') cp = configparser.ConfigParser(interpolation=None, default_section='') cp.read(path, encoding='ASCII') section = cp['formats'] misc.check_sorted(section) return { name: frozenset(examples.split()) for name, examples in section.items() } string_formats = _read_string_formats() # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/iconv.py0000644000000000000000000002350613733665553016102 0ustar00rootroot00000000000000# Copyright © 2012-2017 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' # no coverage 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): 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 sts=4 sw=4 et i18nspector-0.26/lib/intexpr.py0000644000000000000000000004354513733665553016462 0ustar00rootroot00000000000000# Copyright © 2012-2016 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. ''' C integer expressions ''' import ast import functools import types import rply import rply.errors LexingError = rply.errors.LexingError ParsingError = rply.errors.ParsingError # https://git.savannah.gnu.org/cgit/gettext.git/tree/gettext-runtime/intl/plural.y?id=v0.18.3#n132 @functools.lru_cache(maxsize=None) def create_lexer(): lg = rply.LexerGenerator() lg.add('IF', r'[?]') lg.add('ELSE', r':') lg.add('OR', r'[|][|]') lg.add('AND', r'[&][&]') lg.add('EQ', r'[!=]=') lg.add('CMP', r'[<>]=?') lg.add('ADDSUB', r'[+-]') lg.add('MULDIV', r'[*/%]') lg.add('NOT', r'!') lg.add('LPAR', r'[(]') lg.add('RPAR', r'[)]') lg.add('VAR', r'n') lg.add('INT', r'[0-9]+') lg.ignore(r'[ \t]+') return lg.build() @functools.lru_cache(maxsize=None) def create_parser(lexer): pg = rply.ParserGenerator( [rule.name for rule in lexer.rules], precedence=[ ('right', ['IF', 'ELSE']), ('left', ['OR']), ('left', ['AND']), ('left', ['EQ']), ('left', ['CMP']), ('left', ['ADDSUB']), ('left', ['MULDIV']), ('right', ['NOT']), ], cache_id='i18nspector-intexpr', ) ast_bool = { '&&': ast.And(), '||': ast.Or(), } ast_cmp = { '==': ast.Eq(), '!=': ast.NotEq(), '<': ast.Lt(), '<=': ast.LtE(), '>': ast.Gt(), '>=': ast.GtE(), } ast_arithmetic = { '+': ast.Add(), '-': ast.Sub(), '*': ast.Mult(), '/': ast.Div(), '%': ast.Mod(), } ast_not = ast.Not() # pylint: disable=unused-variable @pg.production('start : exp') def eval_start(p): [exp] = p return ast.Expr(exp) @pg.production('exp : exp IF exp ELSE exp') def expr_ifelse(p): [cond, _, body, _, orelse] = p return ast.IfExp(cond, body, orelse) @pg.production('exp : exp OR exp') @pg.production('exp : exp AND exp') def expr_bool(p): [left, tok, right] = p op = ast_bool[tok.getstr()] return ast.BoolOp(op, [left, right]) @pg.production('exp : exp EQ exp') @pg.production('exp : exp CMP exp') def expr_cmp(p): [left, tok, right] = p op = ast_cmp[tok.getstr()] return ast.Compare(left, [op], [right]) @pg.production('exp : exp ADDSUB exp') @pg.production('exp : exp MULDIV exp') def expr_arithmetic(p): [left, tok, right] = p op = ast_arithmetic[tok.getstr()] return ast.BinOp(left, op, right) @pg.production('exp : NOT exp') def expr_not(p): [_, value] = p return ast.UnaryOp(ast_not, value) @pg.production('exp : LPAR exp RPAR') def expr_par(p): [_, exp, _] = p return exp @pg.production('exp : VAR') def expr_var(p): [tok] = p ident = tok.getstr() assert ident == 'n' return ast.Name(ident, ast.Load()) @pg.production('exp : INT') def expr_int(p): [tok] = p n = int(tok.getstr()) return ast.Num(n) # pylint: enable=unused-variable with misc.throwaway_tempdir('rply'): # Use private temporary directory # to mitigate RPLY's insecure use of /tmp: # CVE-2014-1604, CVE-2014-1938 return pg.build() class Parser(): def __init__(self): self._lexer = create_lexer() self._parser = create_parser(self._lexer) def parse(self, s): tokens = self._lexer.lex(s) node = self._parser.parse(tokens) return Expression(node) from lib import misc # pylint: disable=wrong-import-position class BaseEvaluator(): def __init__(self, node): self._ctxt = types.SimpleNamespace() 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 AttributeError: # no coverage 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): assert len(node.comparators) == len(node.ops) if len(node.ops) != 1: raise NotImplementedError left = node.left [op] = node.ops [right] = node.comparators left = self._visit(left) if left is None: return right = self._visit(right) if right is None: return return self._visit(op, left, right) # 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 # pylint: disable=unused-argument # 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_not(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) # constants, variables # ==================== def _visit_num(self, node): return self._check_overflow(node.n) _visit_constant = _visit_num def _visit_name(self, node): return self._check_overflow(self._ctxt.n) # pylint: enable=unused-argument class CodomainEvaluator(BaseEvaluator): def __init__(self, node, *, bits): super().__init__(node) self._ctxt.max = 1 << bits # pylint: disable=unused-argument # 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_not(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]), ) # constants, variables # ==================== def _visit_num(self, node): n = node.n if (n < 0) or (n >= self._ctxt.max): return return (n, n) _visit_constant = _visit_num def _visit_name(self, node): return (0, self._ctxt.max - 1) # pylint: enable=unused-argument def gcd(x, y): while y: (x, y) = (y, x % y) return x def lcm(x, *ys): r = x for y in ys: r //= gcd(r, y) r *= y return r class PeriodEvaluator(BaseEvaluator): def __init__(self, node, *, bits): super().__init__(node) self._ctxt.max = 1 << bits # binary operators # ================ def _visit_binop(self, node): const_mod = ( isinstance(node.op, ast.Mod) and isinstance(node.left, ast.Name) and isinstance(node.right, ast.Num) ) if const_mod: n = node.right.n if (n <= 0) or (n >= self._ctxt.max): return return (0, n) x = self._visit(node.left) if x is None: return y = self._visit(node.right) if y is None: return (xo, xp) = x (yo, yp) = y ro = max(xo, yo) rp = lcm(xp, yp) if rp >= self._ctxt.max: return else: return (ro, rp) # unary operators # =============== def _visit_unaryop(self, node): return self._visit(node.operand) # comparison operators # ==================== def _visit_compare(self, node): assert len(node.comparators) == len(node.ops) if len(node.ops) != 1: raise NotImplementedError [op] = node.ops [right] = node.comparators const_cmp = ( isinstance(node.left, ast.Name) and isinstance(right, ast.Num) ) if const_cmp: n = right.n if (n < 0) or (n >= self._ctxt.max): return # (n N) is constant starting with either N or N+1, # depending on : # # …N-1 N N+1 N+2… # -------+---+---+---+---- # n != N | 1 . 0 . 1 . 1 # n == N | 0 . 1 . 0 . 0 # n <= N | 1 . 1 . 0 . 0 # n > N | 0 . 0 . 1 . 1 # -------+---+---+---+---- # n < N | 1 . 0 . 0 . 0 # n >= N | 0 . 1 . 1 . 1 # -------+---+---+---+---- if isinstance(op, (ast.Lt, ast.GtE)): return (n, 1) else: if n + 1 == self._ctxt.max: return return (n + 1, 1) x = self._visit(node.left) if x is None: return y = self._visit(right) if y is None: return (xo, xp) = x (yo, yp) = y ro = max(xo, yo) rp = lcm(xp, yp) if rp >= self._ctxt.max: return else: return (ro, rp) # boolean operators # ================= def _visit_boolop(self, node): (xo, xp) = (0, 1) for arg in node.values: y = self._visit(arg) if y is None: return (yo, yp) = y xo = max(xo, yo) xp = lcm(xp, yp) if xp >= self._ctxt.max: return return (xo, xp) # if-then-else expression # ======================= def _visit_ifexp(self, node): test = self._visit(node.test) if test is None: return (to, tp) = test x = self._visit(node.body) if x is None: return (xo, xp) = x y = self._visit(node.orelse) if y is None: return (yo, yp) = y ro = max(to, xo, yo) rp = lcm(tp, xp, yp) if rp >= self._ctxt.max: return else: return (ro, rp) # constants, variables # ==================== def _visit_num(self, node): n = node.n if n < 0 or n >= self._ctxt.max: return return (0, 1) _visit_constant = _visit_num def _visit_name(self, node): # pylint: disable=unused-argument pass class Expression(): def __init__(self, node): if not isinstance(node, ast.Expr): raise TypeError # no coverage 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 * (L, R) such that for every n: L ≤ f(n) ≤ R * or None ''' e = CodomainEvaluator(self._node, bits=bits) return e() def period(self, *, bits=32): ''' return * (O, P) such that for every n ≥ O: f(n + P) = f(n) * or None ''' e = PeriodEvaluator(self._node, bits=bits) return e() # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/ling.py0000644000000000000000000002636213733665553015720 0ustar00rootroot00000000000000# Copyright © 2012-2016 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 lib import misc from lib 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(): 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') # no coverage 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() # pylint: disable=protected-access 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 # no coverage # 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 UnicodeEncodeError: pass else: return result for character in characters: try: character.encode(encoding) except UnicodeEncodeError as exc: result += [character] if exc.reason.startswith('iconv:'): # pylint: disable=no-member # 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 __repr__(self): return ''.format(self) 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') cfg_iso_639 = cp['language-codes'] misc.check_sorted(cfg_iso_639) iso_639 = {} for lll, ll in cfg_iso_639.items(): if ll: iso_639[ll] = ll iso_639[lll] = ll else: iso_639[lll] = lll cfg_iso_3166 = cp['territory-codes'] misc.check_sorted(cfg_iso_3166) iso_3166 = frozenset(cc.upper() for cc in cfg_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 key in section.keys(): if key in {'names', 'characters', 'macrolanguage', 'plural-forms', 'principal-territory'}: continue if key.startswith('characters@'): continue raise misc.DataIntegrityError('unknown key: {}'.format(key)) 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: # no coverage 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) if result is not None: 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 sts=4 sw=4 et i18nspector-0.26/lib/misc.py0000644000000000000000000000543713733665553015722 0ustar00rootroot00000000000000# Copyright © 2012-2016 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 contextlib import datetime import tempfile def unsorted(iterable): ''' if the iterable is sorted, return None; otherwise return first (x, y) such that x > y ''' iterable = iter(iterable) for x in iterable: break for y in iterable: if x > y: # pylint: disable=undefined-loop-variable return (x, y) # pylint: disable=undefined-loop-variable x = y class DataIntegrityError(Exception): pass def check_sorted(iterable, exception=DataIntegrityError): ''' raise exception if the iterable is not sorted ''' cx = unsorted(iterable) if cx is not None: raise exception('{0!r} > {1!r}'.format(*cx)) def sorted_vk(d): ''' iterate over d.values() in the key order ''' for k, v in sorted(d.items()): del k yield v def utc_now(): ''' timezone-aware variant of datetime.now() ''' return datetime.datetime.now( datetime.timezone.utc ) def format_range(rng, *, max): # pylint: disable=redefined-builtin 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)) @contextlib.contextmanager def throwaway_tempdir(context): with tempfile.TemporaryDirectory(prefix='i18nspector.{}.'.format(context)) as new_tempdir: original_tempdir = tempfile.tempdir try: tempfile.tempdir = new_tempdir yield finally: tempfile.tempdir = original_tempdir # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/moparser.py0000644000000000000000000001672713733665553016623 0ustar00rootroot00000000000000# Copyright © 2013-2018 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: # * https://git.savannah.gnu.org/cgit/gettext.git/tree/gettext-runtime/intl/gmo.h?id=v0.18.3 # * https://git.savannah.gnu.org/cgit/gettext.git/tree/gettext-tools/src/read-mo.c?id=v0.18.3 # * https://www.gnu.org/software/gettext/manual/html_node/MO-Files.html import re import struct import polib from lib import encodings little_endian_magic = b'\xDE\x12\x04\x95' big_endian_magic = little_endian_magic[::-1] class SyntaxError(Exception): # pylint: disable=redefined-builtin pass class Parser(): 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) view = view.cast('c') if len(view) > 0: 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(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'': # https://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' elif not encodings.is_ascii_compatible_encoding(encoding): encoding = 'ASCII' self._encoding = encoding elif msgids == self._last_msgid: raise SyntaxError('duplicate message definition') elif msgid < self._last_msgid: raise SyntaxError('messages are not sorted') self._last_msgid = msgid # pylint: disable=attribute-defined-outside-init 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.comment = None entry.occurrences = () entry.flags = () # https://bitbucket.org/izi/polib/issues/47 entry.translated = lambda: True entry.previous_msgctxt = None entry.previous_msgid = None entry.previous_msgid_plural = None return entry __all__ = ['Parser', 'SyntaxError'] def main(): import argparse # pylint: disable=import-outside-toplevel ap = argparse.ArgumentParser(description='msgunfmt(1) replacement') ap.add_argument('files', metavar='', nargs='+') options = ap.parse_args() for path in options.files: escaped_path = ascii(path)[1:-1] print('# ' + escaped_path, end='\n\n') parser = Parser(path) for entry in parser.parse(): print(entry) if __name__ == '__main__': main() else: del main # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/paths.py0000644000000000000000000000255413733665553016103 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 sts=4 sw=4 et i18nspector-0.26/lib/polib4us.py0000644000000000000000000001664113733665553016527 0ustar00rootroot00000000000000# Copyright © 2012-2019 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 lib import encodings from lib import moparser # pylint: disable=protected-access patches = [] def install_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: https://bugs.debian.org/692283 # - trailing comment parsing: https://bitbucket.org/izi/polib/issues/51 # - atypical comment parsing # - parsing of empty files: https://bitbucket.org/izi/polib/issues/59 class Codecs(): _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): del self, args, kwargs polib.POFile.find = pofile_find # polib.unescape() # ================ # Work around an escape sequence decoding bug. # https://bitbucket.org/izi/polib/issues/31 _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') # pylint: disable=no-member 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) # pylint: disable=no-member 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/issues/36 # https://bitbucket.org/izi/polib/issues/44 # https://bitbucket.org/izi/polib/issues/45 # https://bitbucket.org/izi/polib/issues/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 # polib.POEntry.flags # =================== # Fix flag splitting. # polib (<< 1.0.4) incorrectly requires that the flag-splitting comma must be # followed by a space. # https://bitbucket.org/izi/polib/issues/46 @register_patch def poentry_flags_patch(): def get_flags(self): return self._i18nspector_flags def set_flags(self, flags): self._i18nspector_flags = [ flag.strip(' \t\r\f\v') for subflags in flags for flag in subflags.split(',') ] polib.POEntry.flags = property(get_flags, set_flags) # polib.POEntry.msgstr_plural # =========================== # Force msgstr_plural keys to be integers. # polib (<< 1.0.4) uses strings there instead. # https://bitbucket.org/izi/polib/issues/49 class IntDict(dict): def __setitem__(self, key, value): super().__setitem__(int(key), value) def __getitem__(self, key): return super().__getitem__(int(key)) @register_patch def poentry_msgstr_plural_patch(): def get_msgstr_plural(self): return self._i18nspector_msgstr_plural def set_msgstr_plural(self, d): self._i18nspector_msgstr_plural = IntDict(d) polib.POEntry.msgstr_plural = property( get_msgstr_plural, set_msgstr_plural, ) # polib._BaseEntry.__init__() # =========================== # Distinguish between empty and non-existent msgid_plural. # Distinguish between empty and non-existent msgstr. @register_patch def base_entry_init_patch(): def init(self, *args, **kwargs): original(self, *args, **kwargs) if 'msgid_plural' not in kwargs: self.msgid_plural = None if 'msgstr' not in kwargs: self.msgstr = None original = polib._BaseEntry.__init__ polib._BaseEntry.__init__ = init # polib.POEntry.translated() # ========================== # Consider the message translated if any msgstr[N] is non-empty. @register_patch def poentry_translated_patch(): def translated(self): if self.obsolete: return False if 'fuzzy' in self.flags: return False return ( self.msgstr or any(self.msgstr_plural.values()) ) polib.POEntry.translated = translated # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/strformat/0000755000000000000000000000000013733665553016425 5ustar00rootroot00000000000000i18nspector-0.26/lib/strformat/__init__.py0000644000000000000000000000000013733665553020524 0ustar00rootroot00000000000000i18nspector-0.26/lib/strformat/c.py0000644000000000000000000004002413733665553017221 0ustar00rootroot00000000000000# Copyright © 2014-2018 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 format checks: C ''' import collections import re _directive_re = re.compile(''' (?P [^%]+ ) | ( % (?P [0-9]+[$] )? (?P [#0 +'I-]* ) (?: (?P [1-9][0-9]* ) | (?P [*] ) (?P [0-9]+[$] )? )? (?: [.] (?: (?P [0-9]* ) | (?P [*] ) (?P [0-9]+[$] )? ) )? (?: (?P hh? | ll? | [qjzZt] | L )? (?P [diouxXeEfFgGaAcsCSpnm%] ) | < (?: PRI (?P[diouxX]) (?P (?:LEAST|FAST)?(?:8|16|32|64)|MAX|PTR) ) > ) ) ''', re.VERBOSE) def _printable_prefix(s, r=re.compile('[ -\x7E]+')): return r.match(s).group() class _info: oct_cvt = 'o' hex_cvt = 'xXaA' dec_cvt = 'diufFgG' float_cvt = 'aAeEfFgG' uint_cvt = 'ouxX' int_cvt = 'di' + uint_cvt str_cvt = 'sS' int_types = ''' hh = signed char | unsigned char h = short int | unsigned short int l = long int | unsigned long int ll = long long int | unsigned long long int j = intmax_t | uintmax_t z = ssize_t | size_t t = ptrdiff_t | [unsigned ptrdiff_t] = int | unsigned int ''' int_types = dict( (key, tuple(str.strip(v) for v in values.split('|'))) for line in int_types.strip().splitlines() for key, values in [map(str.strip, line.split('='))] ) # FIXME: The printf(3) manpage says that the type for signed integer with # “z“ size is ssize_t. # But SUSv3 says it's a signed integer type corresponding to size_t, # which is not necessarily the same thing as ssize_t. # https://www.gnu.org/software/libc/manual/html_node/Integer-Conversions.html portable_int_lengths = dict( L='ll', # The use of “L” with integer conversions is not documented # in the printf(3) manpage. https://bugs.debian.org/757151 q='ll', Z='z', ) INT_MAX = (1 << 31) - 1 # on most architectures NL_ARGMAX = 4096 # on GNU/Linux class Error(Exception): message = 'invalid conversion specification' class NonPortableConversion(Error): message = 'non-portable conversion specifier or length modifier' # errors in argument indexing: class ForbiddenArgumentIndex(Error): message = 'argument index not allowed' class ArgumentRangeError(Error): message = 'argument index too small or too large' class MissingArgument(Error): message = 'missing argument' class ArgumentTypeMismatch(Error): message = 'argument type mismatch' class ArgumentNumberingMixture(Error): message = 'mixed numbered and unnumbered argument specifications' # errors in length modifiers: class LengthError(Error): message = 'invalid length modifier' # errors in flag characters: class FlagError(Error): message = 'unexpected format flag character' class RedundantFlag(Error): message = 'redundant flag character' # errors in field width: class WidthError(Error): message = 'unexpected width' class WidthRangeError(Error): message = 'field width too large' # errors in precision: class PrecisionError(Error): message = 'unexpected precision' class PrecisionRangeError(Error): message = 'precision too large' class VariableWidth(): type = 'int' def __init__(self, parent): self.parent = parent class VariablePrecision(): type = 'int' def __init__(self, parent): self.parent = parent class FormatString(): def __init__(self, s): self._items = items = [] self._argument_map = collections.defaultdict(list) self._next_arg_index = 1 self.warnings = [] last_pos = 0 for match in _directive_re.finditer(s): if match.start() != last_pos: raise Error( _printable_prefix(s[last_pos:]) ) last_pos = match.end() literal = match.group('literal') if literal is not None: items += [literal] else: items += [Conversion(self, match)] if last_pos != len(s): raise Error( _printable_prefix(s[last_pos:]) ) self.arguments = [] for i in range(1, NL_ARGMAX + 1): if not self._argument_map: break try: args = self._argument_map.pop(i) except KeyError: raise MissingArgument(s, i) self.arguments += [args] assert not self._argument_map self._argument_map = None for i, args in enumerate(self.arguments, start=1): types = frozenset(a.type for a in args) if len(types) > 1: raise ArgumentTypeMismatch(s, i, types) def add_argument(self, n, value): if self._argument_map is None: raise RuntimeError('arguments already initialized') if n is None: if self._next_arg_index is None: raise IndexError else: n = self._next_arg_index self._next_arg_index += 1 elif self._next_arg_index is None: pass elif self._next_arg_index == 1: assert not self._argument_map self._next_arg_index = None else: raise IndexError if n > NL_ARGMAX: raise OverflowError(n) self._argument_map[n] += [value] def warn(self, exc_type, *args, **kwargs): self.warnings += [exc_type(*args, **kwargs)] def get_last_integer_conversion(self, *, n): ''' return the integer conversion that consumes the last n arguments, or None ''' if n > len(self.arguments): raise IndexError if n <= 0: raise IndexError conv = vconv = None for i in range(len(self.arguments) - n, len(self.arguments)): assert i >= 0 for arg in self.arguments[i]: if isinstance(arg, (VariableWidth, VariablePrecision)): if vconv is None: vconv = arg.parent if vconv is not arg.parent: return elif isinstance(arg, Conversion): if vconv is None: vconv = arg if (conv is None) and (vconv is arg): conv = arg if conv is not arg: return else: assert False, 'type(arg) == {!r}'.format(type(arg)) # no coverage if conv is None: return if not conv.integer: return return conv def __iter__(self): return iter(self._items) def __len__(self): return len(self._items) class Conversion(): type = None integer = None def __init__(self, parent, match): i = _info self._s = s = match.string[slice(*match.span())] # length and conversion: c99conversion = match.group('c99conv') c99length = match.group('c99len') length = match.group('length') conversion = match.group('conversion') tp = None self.integer = False if c99conversion is not None: assert c99length is not None if c99conversion in 'di': tp = 'int' elif c99conversion in 'ouxX': tp = 'uint' else: # should not happen assert False # no coverage conversion = c99conversion if c99length.startswith(('LEAST', 'FAST')): tp += '_' + c99length.lower() else: tp += c99length.lower() tp += '_t' self.integer = True elif conversion in i.int_cvt + 'n': plength = i.portable_int_lengths.get(length, length) if plength != length: parent.warn(NonPortableConversion, s, '%' + length + conversion, '%' + plength + conversion ) tp = i.int_types.get(plength or '') # pylint: disable=no-member assert tp is not None tp = tp[conversion in i.uint_cvt] if conversion == 'n': tp += ' *' else: self.integer = True elif conversion in i.float_cvt: if length is None: tp = 'double' elif length == 'l': # XXX C99 says that the “l” length is no-op for floating-point # conversions, but this is not documented in the printf(3) # manpage. parent.warn(NonPortableConversion, s, '%l' + conversion, '%' + conversion ) tp = 'double' elif length == 'L': tp = 'long double' elif conversion == 'c': if length is None: tp = 'char' # C99 says it's an int, which is then converted to unsigned char. # We don't want “int” here, so that %c and %d have distinct types. # Mere “char” is not very precise, but it should be good enough. elif length == 'l': tp = 'wint_t' elif conversion == 'C': if length is None: parent.warn(NonPortableConversion, s, '%C', '%lc') tp = 'wint_t' elif conversion == 's': if length is None: tp = 'const char *' elif length == 'l': tp = 'const wchar_t *' elif conversion == 'S': if length is None: parent.warn(NonPortableConversion, s, '%S', '%ls') tp = 'const wchar_t *' elif conversion == 'p': if length is None: tp = 'void *' elif conversion in {'m', '%'}: if length is None: tp = 'void' else: # should not happen assert False # no coverage if tp is None: assert length is not None raise LengthError(s, length) self.type = tp # flags: flags = collections.Counter(match.group('flags')) for flag, count in flags.items(): if count != 1: parent.warn(RedundantFlag, s, flag, flag) if conversion == 'n': # C99 says that the “n” conversion cannot include any flags, # but this is not documented in the printf(3) manpage. # https://bugs.debian.org/756602 raise FlagError(s, flag) if flag == '#': if conversion not in i.oct_cvt + i.hex_cvt + i.float_cvt: raise FlagError(s, flag) elif flag == '0': if conversion not in i.int_cvt + i.float_cvt: raise FlagError(s, flag) elif flag == "'": if conversion not in i.dec_cvt: raise FlagError(s, flag) else: if conversion == '%': raise FlagError(s, flag) assert flag in {'-', ' ', '+', 'I'} for f1, f2 in [('-', '0'), ('+', ' ')]: if (f1 in flags) and (f2 in flags): parent.warn(RedundantFlag, s, f1, f2) # width: width = match.group('width') if width is not None: width = int(width) if width > INT_MAX: raise WidthRangeError(s, width) elif match.group('varwidth'): varwidth_index = match.group('varwidth_index') if varwidth_index is not None: varwidth_index = int(varwidth_index.rstrip('$')) if not (0 < varwidth_index <= NL_ARGMAX): raise ArgumentRangeError(s, varwidth_index) try: parent.add_argument(varwidth_index, VariableWidth(self)) except IndexError: raise ArgumentNumberingMixture(s) except OverflowError as exc: raise ArgumentRangeError(s, '{}$'.format(exc)) width = ... if width is not None: if conversion in '%n': # C99 says that the “n” conversion cannot include a field width, # but this is not documented in the printf(3) manpage. # https://bugs.debian.org/756602 raise WidthError(s) # precision: precision = match.group('precision') if precision is not None: precision = int(precision or '0') if precision > INT_MAX: raise PrecisionRangeError(s) elif match.group('varprec'): varprec_index = match.group('varprec_index') if varprec_index is not None: varprec_index = int(varprec_index.rstrip('$')) if not (0 < varprec_index <= NL_ARGMAX): raise ArgumentRangeError(s, varprec_index) try: parent.add_argument(varprec_index, VariablePrecision(self)) except IndexError: raise ArgumentNumberingMixture(s) except OverflowError as exc: raise ArgumentRangeError(s, '{}$'.format(exc)) precision = ... if precision is not None: if conversion in i.int_cvt + i.float_cvt + i.str_cvt: pass else: # XXX C99 says that precision for the other conversion is # undefined behavior, but this is not documented in the # printf(3) manpage. raise PrecisionError(s) if (conversion in i.int_cvt) and ('0' in flags): parent.warn(RedundantFlag, s, '0') # index: index = match.group('index') if index is not None: index = int(index.rstrip('$')) if not (0 < index <= NL_ARGMAX): raise ArgumentRangeError(s, index) if tp == 'void': if index is not None: if conversion == '%': raise ForbiddenArgumentIndex(s) else: # Although not specifically forbidden, having an argument index # for %m (which doesn't consume any argument) doesn't make any # sense. TODO: Emit a warning. pass # XXX The printf(3) manpage says that numbered arguments can be # mixed only with %%. But practically, mixing them with %m (which # also doesn't consume any argument) must be also allowed. else: try: parent.add_argument(index, self) except IndexError: raise ArgumentNumberingMixture(s) except OverflowError as exc: raise ArgumentRangeError(s, '{}$'.format(exc)) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/strformat/perlbrace.py0000644000000000000000000000436413733665553020745 0ustar00rootroot00000000000000# Copyright © 2016-2020 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. ''' Perl format checks: Locale::TextDomain ''' import re _field_re = re.compile(r''' (?P [^{]+ ) | (?: [{] (?P [^\W\d]\w* ) [}] ) ''', re.VERBOSE) def _printable_prefix(s, r=re.compile('[ -\x7E]+')): return r.match(s).group() class Error(Exception): message = 'invalid placeholder specification' class FormatString(): def __init__(self, s): self._items = items = [] arguments = set() last_pos = 0 for match in _field_re.finditer(s): if match.start() != last_pos: raise Error( _printable_prefix(s[last_pos:]) ) items += [match.group()] argname = match.group('name') if argname is not None: arguments.add(argname) last_pos = match.end() if last_pos != len(s): raise Error( _printable_prefix(s[last_pos:]) ) self.arguments = frozenset(arguments) def __iter__(self): return iter(self._items) def __len__(self): return len(self._items) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/strformat/pybrace.py0000644000000000000000000002150213733665553020424 0ustar00rootroot00000000000000# Copyright © 2016-2020 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 format checks: Python's str.format() ''' import collections import functools import re _field_name_pattern = r''' (?: \d+ | [^\W\d]\w* ) (?: [.] [^\W\d]\w* | \[ [^]]+ \] )* ''' _simple_field_pattern = '[{] (?:' + _field_name_pattern + ') ? [}]' _simple_field_re = re.compile(_simple_field_pattern, re.VERBOSE) _field_re = re.compile(r''' (?P (?: [^{}] | [{]{2} | [}]{2} )+ ) | (?: [{] (?: (?P''' + _field_name_pattern + r''') ? (?P ! \w+ ) ? (?P : (?: [^{}]* | ''' + _simple_field_pattern + ''' )* ) ? ) [}] ) ''', re.VERBOSE) _format_spec_re = re.compile( # (this regex doesn't take nested fields into account) r''' \A (?: (?P [^}] ) ? (?P [<>=^] ) ) ? (?P [ +-] ) ? (?P [#] ) ? (?P [0] ) ? (?P [0-9]+ ) ? (?P [,] ) ? (?: [.] (?P \d+) ) ? (?P [\w%]) ? \Z ''', re.VERBOSE) def _printable_prefix(s, r=re.compile('[ -\x7E]+')): return r.match(s).group() # -------------------------------------------------------------------------- SSIZE_MAX = (1 << 31) - 1 # on 32-bit architectures # -------------------------------------------------------------------------- class Error(Exception): message = 'invalid replacement field specification' class ConversionError(Error): message = 'invalid conversion flag' class FormatError(Error): message = 'invalid format specification' class FormatTypeMismatch(Error): message = 'type mismatch between conversion and format specifications' # errors in argument indexing: class ArgumentNumberingMixture(Error): message = 'mixed numbered and unnumbered argument specifications' class ArgumentRangeError(Error): message = 'argument index too large' class ArgumentTypeMismatch(Error): message = 'argument type mismatch' # -------------------------------------------------------------------------- class FormatString(): def __init__(self, s): self._argument_map = collections.defaultdict(list) self._next_arg_index = 0 self._items = items = [] last_pos = 0 for match in _field_re.finditer(s): if match.start() != last_pos: raise Error( _printable_prefix(s[last_pos:]) ) last_pos = match.end() literal = match.group('literal') if literal is not None: items += [literal] else: items += [Field(self, match)] if last_pos != len(s): raise Error( _printable_prefix(s[last_pos:]) ) for name, args in self._argument_map.items(): common_types = functools.reduce( frozenset.__and__, (a.types for a in args) ) if not common_types: raise ArgumentTypeMismatch(s, name) for arg in args: arg.types = common_types self.argument_map = dict(self._argument_map) self._argument_map = None def add_argument(self, name, field): if self._argument_map is None: raise RuntimeError('arguments already initialized') if name is None: if self._next_arg_index is None: raise IndexError n = self._next_arg_index if n > SSIZE_MAX: raise OverflowError(n) self._next_arg_index += 1 self._argument_map[n] += [field] elif name.isdigit(): n = int(name) if n > SSIZE_MAX: raise OverflowError(n) if self._next_arg_index is None: pass elif self._next_arg_index == 0: self._next_arg_index = None else: raise IndexError self._argument_map[n] += [field] else: self._argument_map[name] += [field] def __iter__(self): return iter(self._items) def __len__(self): return len(self._items) # -------------------------------------------------------------------------- class Field(): def __init__(self, parent, match): s = match.string[slice(*match.span())] name = match.group('name') try: parent.add_argument(name, self) except IndexError: raise ArgumentNumberingMixture(s) except OverflowError: raise ArgumentRangeError(s) fmt = match.group('format') tp = {'str', 'int', 'float'} if fmt is None: pass elif '{' in fmt: # Nested replacement fields are nasty. They make virtually # impossible to do any type checking. For example: # # >>> '{:{}{}}'.format('m', 'o<2', 3) # 'moooooooooooooooooooooo' # >>> '{:{}{}}'.format(23, '+', 'x') # '+17' # for subfield in _simple_field_re.findall(fmt): assert subfield[0] == '{' assert subfield[-1] == '}' subfield_name = subfield[1:-1] or None subfield = NestedField(self) try: parent.add_argument(subfield_name, subfield) except IndexError: raise ArgumentNumberingMixture(subfield) except OverflowError: raise ArgumentRangeError(s) else: assert fmt[0] == ':' fmatch = _format_spec_re.match(fmt[1:]) if fmatch is None: raise FormatError(s) comma = fmatch.group('comma') ftype = fmatch.group('type') if ftype is None: pass elif ftype == 's': tp = {'str'} elif ftype in 'bcdoxX': tp = {'int'} elif ftype in 'eEfFgG%': tp = {'float'} elif ftype == 'n': if comma: raise FormatError(s) tp = {'int', 'float'} else: raise Error(s) alt = fmatch.group('alt') sign = fmatch.group('sign') if alt or sign or comma: tp &= {'int', 'float'} if not tp: raise FormatError(s) align = fmatch.group('align') zero = fmatch.group('zero') if (align is None) and (zero is not None): align = '=' if align == '=': tp &= {'int', 'float'} if not tp: raise FormatError(s) width = fmatch.group('width') if width is not None: width = int(width) if width > SSIZE_MAX: raise FormatError(s) precision = fmatch.group('precision') if precision is not None: tp &= {'float', 'str'} if not tp: raise FormatError(s) precision = int(precision) if precision > SSIZE_MAX: raise FormatError(s) conversion = match.group('conversion') if conversion is None: pass elif conversion in {'!s', '!r', '!a'}: if 'str' not in tp: raise FormatTypeMismatch(s) else: raise ConversionError(s) self.types = frozenset(tp) class NestedField(): types = frozenset({'str', 'int', 'float'}) def __init__(self, parent): self.parent = parent # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/strformat/python.py0000644000000000000000000002315213733665553020323 0ustar00rootroot00000000000000# Copyright © 2015-2018 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 format checks: Python's %-formatting ''' import collections import io class _info: flags = '#0- +' lengths = 'hlL' oct_cvt = 'o' hex_cvt = 'xX' int_cvt = oct_cvt + hex_cvt + 'diu' float_cvt = 'eEfFgG' other_cvt = 'csra' all_cvt = int_cvt + float_cvt + other_cvt + '%' SSIZE_MAX = (1 << 31) - 1 # on 32-bit architectures # -------------------------------------------------------------------------- class Error(Exception): message = 'invalid conversion specification' class ObsoleteConversion(Error): message = 'obsolete conversion specifier' # errors in argument indexing: class ForbiddenArgumentKey(Error): message = 'argument key not allowed' class ArgumentIndexingMixture(Error): message = 'mixed named and unnamed argument specifications' class ArgumentTypeMismatch(Error): message = 'argument type mismatch' # errors is flags: class RedundantFlag(Error): message = 'redundant flag character' # errors in field width: class WidthRangeError(Error): message = 'field width too large' # errors in precision: class RedundantPrecision(Error): message = 'redundant precision' class PrecisionRangeError(Error): message = 'precision too large' # errors in length modifiers: class RedundantLength(Error): message = 'redundant length modifier' # -------------------------------------------------------------------------- class VariableWidth(): type = 'int' def __init__(self, parent): self.parent = parent class VariablePrecision(): type = 'int' def __init__(self, parent): self.parent = parent # -------------------------------------------------------------------------- class FormatString(): def __init__(self, s): self._items = items = [] self._seq_arguments = [] self._map_arguments = collections.defaultdict(list) self.warnings = [] text = io.StringIO() si = enumerate(s) i = 0 def next_si(): try: return next(si) except StopIteration: raise Error(s[i:]) while True: try: i, ch = next(si) except StopIteration: if text.tell(): items += [text.getvalue()] break if ch != '%': text.write(ch) continue j, ch = next_si() key = None if ch == '(': # XXX Python skips over balanced parentheses, but this is not documented. pcount = 1 while True: j, ch = next_si() if ch == '(': pcount += 1 elif ch == ')': pcount -= 1 if pcount == 0: j, ch = next_si() break key = s[i+2:j-1] flags = collections.Counter() while ch in _info.flags: flags[ch] += 1 j, ch = next_si() width = None var_width = False if ch == '*': var_width = True j, ch = next_si() else: width = 0 while '0' <= ch <= '9': width *= 10 width += int(ch) j, ch = next_si() prec = None var_prec = False if ch == '.': j, ch = next_si() if ch == '*': var_prec = True j, ch = next_si() else: prec = 0 while '0' <= ch <= '9': prec *= 10 prec += int(ch) j, ch = next_si() length = None if ch in _info.lengths: length = ch j, ch = next_si() if ch in _info.all_cvt: conv = ch else: raise Error(s[i:]) if text.tell(): items += [text.getvalue()] text.seek(0) text.truncate() items += [Conversion(self, s[i:j+1], key=key, flags=flags, width=width, var_width=var_width, prec=prec, var_prec=var_prec, length=length, conv=conv, )] self.seq_arguments = self._seq_arguments self.seq_conversions = [ arg for arg in self._seq_arguments if isinstance(arg, Conversion) ] for key, args in self._map_arguments.items(): types = frozenset(a.type for a in args) if len(types) > 1: raise ArgumentTypeMismatch(s, key, types) self.map_arguments = self._map_arguments self._map_arguments = self._seq_arguments = None def add_argument(self, key, arg): if self._map_arguments is None: raise RuntimeError('arguments already initialized') # Python accepts mixed named and unnamed arguments # in some corner cases: # https://bugs.python.org/issue1467929 # We follow the documentation and reject such mixtures. if key is None: if self._map_arguments: raise IndexError self._seq_arguments += [arg] else: if self._seq_arguments: raise IndexError self._map_arguments[key] += [arg] def warn(self, exc_type, *args, **kwargs): self.warnings += [exc_type(*args, **kwargs)] def __iter__(self): return iter(self._items) def __len__(self): return len(self._items) # -------------------------------------------------------------------------- class Conversion(): def __init__(self, parent, s, *, key, flags, width, var_width, prec, var_prec, length, conv): assert s[-1] == conv, '{0} != {1}'.format(s[-1], conv) i = _info for flag, count in flags.items(): if count != 1: parent.warn(RedundantFlag, s, flag, flag) if flag == '#': if conv not in i.oct_cvt + i.hex_cvt + i.float_cvt: parent.warn(RedundantFlag, s, flag) elif flag == '-': pass else: assert flag in '0 +' if conv not in i.int_cvt + i.float_cvt: parent.warn(RedundantFlag, s, flag) for f1, f2 in [('-', '0'), ('+', ' ')]: if (f1 in flags) and (f2 in flags): parent.warn(RedundantFlag, s, f1, f2) if var_width: assert width is None try: parent.add_argument(None, VariableWidth(self)) except IndexError: raise ArgumentIndexingMixture(s) width = ... elif width > SSIZE_MAX: # The limit is INT_MAX in Python 2.X and SSIZE_MAX in Python 3.X; # but INT_MAX == SSIZE_MAX on mainstream 32-bit architectures. raise WidthRangeError(s, width) if var_prec: assert prec is None try: parent.add_argument(None, VariablePrecision(self)) except IndexError: raise ArgumentIndexingMixture(s) prec = ... elif prec is not None: if prec > SSIZE_MAX: raise PrecisionRangeError(s, width) if prec is not None: if (conv in i.int_cvt) and ('0' in flags): parent.warn(RedundantFlag, s, '0') if conv in 'c%': parent.warn(RedundantPrecision, s, prec) if length is not None: parent.warn(RedundantLength, s, length) if conv in i.int_cvt: tp = 'int' if conv == 'u': parent.warn(ObsoleteConversion, s, '%u', '%d') elif conv in i.float_cvt: tp = 'float' elif conv == 'c': tp = 'chr' elif conv == 's': tp = 'str' elif conv in 'ra': tp = 'object' elif conv == '%': tp = 'None' else: assert False # no coverage self.type = tp if tp == 'None': if key is not None: raise ForbiddenArgumentKey(s) else: try: parent.add_argument(key, self) except IndexError: raise ArgumentIndexingMixture(s) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/lib/tags.py0000644000000000000000000001357613733665553015730 0ustar00rootroot00000000000000# Copyright © 2012-2020 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 enum import functools import os import re from lib import misc from lib import paths from lib import terminal @functools.total_ordering class OrderedEnum(enum.Enum): def __lt__(self, other): if not type(self) is type(other): return NotImplemented return self.value < other.value # pylint: disable=comparison-with-callable def __eq__(self, other): if not type(self) is type(other): return NotImplemented return self.value == other.value # pylint: disable=comparison-with-callable def __hash__(self): # pylint: disable=invalid-hash-returned return self.value severities = OrderedEnum('Severity', [ 'pedantic', 'wishlist', 'minor', 'normal', 'important', 'serious', ]) certainties = OrderedEnum('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(): 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) type({self.name, self.severity, self.certainty}) # pylint: disable=attribute-defined-outside-init 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) # pylint: enable=attribute-defined-outside-init _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 sts=4 sw=4 et i18nspector-0.26/lib/terminal.py0000644000000000000000000000533413733665553016576 0ustar00rootroot00000000000000# Copyright © 2012-2018 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: @staticmethod def tigetstr(*args, **kwargs): del args, kwargs return b'' @staticmethod def tparm(*args, **kwargs): del 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) if s: # work-around for https://bugs.debian.org/902630 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 # pylint: disable=global-statement try: import curses as _curses # pylint: disable=redefined-outer-name,import-outside-toplevel except ImportError: return try: _curses.setupterm() except _curses.error: _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 sts=4 sw=4 et i18nspector-0.26/lib/xml.py0000644000000000000000000000462513733665553015565 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. ''' XML support ''' import random import string import xml.parsers.expat SyntaxError = xml.parsers.expat.ExpatError # pylint: disable=redefined-builtin _xe = ( 'i18nspector.' + ''.join(random.choice(string.ascii_lowercase) for x in range(12)) ) _source = '''\ ]> &{xe}; '''.format(xe=_xe).encode('ASCII') def check_fragment(s): ''' check if the string could be a well-formed XML fragment ''' def ee_handler(context, base, systemid, publicid): assert base is None assert systemid == _xe assert publicid is None eparser = parser.ExternalEntityParserCreate(context) eparser.Parse(s.encode('UTF-8'), True) return 1 parser = xml.parsers.expat.ParserCreate('UTF-8') parser.ExternalEntityRefHandler = ee_handler parser.Parse(_source, True) # https://www.w3.org/TR/REC-xml/#NT-NameStartChar # pylint: disable=line-too-long _start_char = ':A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\U00010000-\U000EFFFF' _next_char = _start_char + '.0-9\xB7\u0300-\u036F\u203F\u2040-' name_re = '[{0}][{1}]*'.format(_start_char, _next_char) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/private/0000755000000000000000000000000013733665555015312 5ustar00rootroot00000000000000i18nspector-0.26/private/add-languages0000755000000000000000000000547313733665553017743 0ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright © 2012-2016 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 functools import subprocess as ipc import sys import json @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/iso-codes/json'.format(prefix=prefix) def main(): ap = argparse.ArgumentParser() ap.add_argument('languages', metavar='', nargs='+') options = ap.parse_args() languages = set(options.languages) path = get_iso_codes_dir() + '/iso_639-2.json' with open(path, 'rt', encoding='UTF-8') as file: data = json.load(file) for item in data['639-2']: ll = item.get('alpha_2') lll_t = item.get('alpha_3') lll_b = item.get('bibliographic') 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 item.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() for lang in sorted(languages): print('# Unknown language code: {}'.format(lang)) sys.exit(len(languages) > 0) if __name__ == '__main__': main() # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/private/check-rst0000755000000000000000000000303313733665553017120 0ustar00rootroot00000000000000#!/bin/sh # Copyright © 2016-2018 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. set -e -u here=${0%/*} here=${here#./} root="$here/../" root=${root#private/../} rst2xml=$(command -v rst2xml) \ || rst2xml=$(command -v rst2xml.py) \ || { printf 'rst2xml not found\n' >&2; exit 1; } rst2xml=${rst2xml##*/} options='--input-encoding=UTF-8 --strict' if [ $# -eq 0 ] then grep -rwl 'ft=rst' "${root}doc" else printf '%s\n' "$@" fi | xargs -L1 -t -I{} "$rst2xml" $options {} /dev/null # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/private/collect-characters0000755000000000000000000000621513733665553021004 0ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright © 2012-2016 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: # pylint: disable=broad-except 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 sts=4 sw=4 et i18nspector-0.26/private/collect-metadata0000755000000000000000000001136013733665553020442 0ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright © 2012-2016 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: # pylint: disable=broad-except 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 sts=4 sw=4 et i18nspector-0.26/private/online-build-po-corpus0000755000000000000000000002020213733665553021540 0ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright © 2012-2020 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 contextlib import gzip import os import re import subprocess import sys import tarfile import tempfile import urllib.parse import apt import apt_pkg def is_po_path(path): return path.endswith(('.po', '.pot')) class Fetcher(): def __init__(self, urlbase): self._urlbase = urlbase self._progress = apt.progress.text.AcquireProgress() self._acquire = apt_pkg.Acquire(self._progress) self._files = [] self._tmpdir = tempfile.TemporaryDirectory(prefix='i18nspector.private.') def add(self, url, name, urlbase=None): if urlbase is None: urlbase = self._urlbase url = urllib.parse.urljoin(urlbase, url) self._files += [apt_pkg.AcquireFile( self._acquire, uri=url, descr=url, destfile=os.path.join(self._tmpdir.name, name) )] def run(self): acq = self._acquire rc = acq.run() if rc != acq.RESULT_CONTINUE: raise RuntimeError('fetching failed') for acqfile in self._files: if acqfile.status != acqfile.STAT_DONE: raise RuntimeError('fetching failed') yield acqfile.destfile def __enter__(self): return self def __exit__(self, exc, value, tb): self.close() def close(self): self._tmpdir.cleanup() _package_name_re = re.compile(r'\A[a-z0-9][a-z0-9.+-]+\Z') def validate_package_name(pkg): if _package_name_re.match(pkg): pass else: raise RuntimeError('invalid package name: {pkg!r}'.format(pkg=pkg)) @contextlib.contextmanager def chdir(new_cwd): orig_cwd = os.getcwd() try: os.chdir(new_cwd) yield finally: os.chdir(orig_cwd) default_mirror = 'https://deb.debian.org/debian' default_dist = 'stable' default_areas = 'main' def main(): ap = argparse.ArgumentParser() ap.add_argument('--mirror', metavar='URL', default=default_mirror, help='Debian mirror to use (default: {mirror})'.format(mirror=default_mirror) ) ap.add_argument('--contents-mirror', metavar='URL', default=None, help='Debian mirror of Contents-* files to use (default: same as --mirror)' ) ap.add_argument('--distribution', metavar='DIST', default=default_dist, help='Debian distribution to use (default: {dist})'.format(dist=default_dist) ) ap.add_argument('--areas', metavar='AREA[,AREA...]', default=default_areas, help='archive areas to use (default: {areas})'.format(areas=default_areas) ) ap.add_argument('--output', metavar='TARFILE', required=True, help='output tar file' ) options = ap.parse_args() output = options.output tarmode = 'w|' for ext in 'gz', 'bz2', 'xz': if options.output.endswith('.' + ext): tarmode += ext break tar = tarfile.open(output, mode=tarmode) mirror = options.mirror cnts_mirror = options.contents_mirror if cnts_mirror is None: cnts_mirror = mirror dist = options.distribution areas = options.areas.split(',') def tarfilter(tarinfo): tarinfo.uid = tarinfo.gid = 0 tarinfo.uname = tarinfo.gname = 'root' tarinfo.mode &= 0o700 tarinfo.mode |= 0o644 if tarinfo.mode & 0o100: tarinfo.mode |= 0o111 prefix = 'po-corpus-{dist}/'.format(dist=dist) tarinfo.name = prefix + tarinfo.name if tarinfo.linkname: tarinfo.linkname = prefix + tarinfo.linkname return tarinfo subprocess.check_call(['dpkg-source', '--version'], stdout=subprocess.DEVNULL) for area in areas: urlbase = '{mirror}/dists/{dist}/{area}/'.format(mirror=mirror, dist=dist, area=area) cnts_urlbase = '{mirror}/dists/{dist}/{area}/'.format(mirror=cnts_mirror, dist=dist, area=area) with Fetcher(urlbase=urlbase) as fetcher: fetcher.add('Contents-source.gz', 'Contents.gz', urlbase=cnts_urlbase) fetcher.add('source/Sources.xz', 'Sources.xz') [contents_path, sources_path] = fetcher.run() interesting_packages = set() with gzip.open(contents_path, 'rt', encoding='UTF-8', newline='\n') as file: for line in file: try: path, packages = line.rsplit('\t', 1) except ValueError: raise RuntimeError('malformed line: {!r}'.format(line)) if is_po_path(path): packages = packages.rstrip('\n').split(',') for pkg in packages: validate_package_name(pkg) interesting_packages.update(packages) for para in apt_pkg.TagFile(sources_path): pkg = para['Package'] if pkg not in interesting_packages: continue fileinfo = para['Files'].splitlines() dscname = None names = set() for line in fileinfo: _, name = line.rsplit(' ', 1) ok = ( name.startswith(pkg + '_') and '/' not in name and name not in names ) if not ok: raise RuntimeError('Package {pkg}: bad Files line: {line!r}'.format(pkg=pkg, line=line)) names.add(name) if name.endswith('.dsc'): if dscname is not None: raise RuntimeError('Package {pkg}: duplicate .dsc file'.format(pkg=pkg)) dscname = name if dscname is None: raise RuntimeError('Package {pkg}: missing .dsc file'.format(pkg=pkg)) names = list(names) names.sort(key=dscname.__eq__) pkgdir = para['Directory'] pkgurlbase = '{mirror}/{dir}/'.format(mirror=mirror, dir=pkgdir) with Fetcher(urlbase=pkgurlbase) as pkgfetcher: for name in names: pkgfetcher.add(name, name) for path in pkgfetcher.run(): pass dscpath = path unpacked = dscpath[:-4] subprocess.check_call(['dpkg-source', '-x', dscpath, unpacked], stdout=sys.stderr) with chdir(os.path.dirname(unpacked)): for unp_root, unp_dirs, unp_files in os.walk(os.path.basename(unpacked)): try: unp_dirs.remove('.pc') except ValueError: pass for unp_file in unp_files: if is_po_path(unp_file): unp_path = os.path.join(unp_root, unp_file) tar.add(unp_path, filter=tarfilter) tar.close() if __name__ == '__main__': main() # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/private/online-check-gettext-data0000755000000000000000000001356013733665553022173 0ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright © 2012-2017 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 re import sys import urllib.request sys.path[0] += '/..' from lib import gettext 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 = 'https://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() or [] if gettext_plural_forms not in our_plural_forms: print('[{}]'.format(language)) if our_plural_forms: 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() blacklist = { # https://lists.gnu.org/archive/html/bug-gettext/2015-06/msg00057.html ('pap', 'AN'), } def do_languages(): url = 'https://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(r'"(\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: if (language, gettext_cc) in blacklist: if our_cc is not None: okay.add(language) continue 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() def do_string_formats(): url = 'https://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') their_formats = frozenset( re.findall(r'"([\w-]+)"', contents) ) our_formats = frozenset( gettext.string_formats.keys() ) difference = their_formats ^ our_formats print('[formats]') for fmt in difference: if fmt in our_formats: print('# MISSING: {fmt} = ...'.format(fmt=fmt)) else: print('{fmt} = # TODO'.format(fmt=fmt)) n_okay = len(our_formats - difference) print('# No changes required for {} string formats'.format(n_okay)) print() def main(): do_plurals() do_languages() do_string_formats() if __name__ == '__main__': main() # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/private/run-pylint0000755000000000000000000000410213733665553017354 0ustar00rootroot00000000000000#!/bin/sh # Copyright © 2015-2019 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=${PYTHON:-python3} "$PYTHON" -m pylint --version >/dev/null || exit 1 if [ $# -eq 0 ] then pyscripts=$(grep -l -r '^#!.*python' .) set -- lib tests tests/fuzzing/*/*.py $pyscripts fi whitelist= ignored= for ext in afl apt_pkg do if "$PYTHON" -c "import $ext" 2>/dev/null then whitelist="$whitelist,$ext" else ignored="$ignored,$ext" fi done if [ -z "${ignored%%*apt*}" ] then ignored="$ignored,apt" fi set -- --extension-pkg-whitelist="${whitelist#,}" --ignored-modules="${ignored#,}" "$@" log=$(mktemp -t pylint.XXXXXX) "$PYTHON" -m pylint "$@" > "$log" || [ $? != 1 ] ! grep -P '^\S+:' "$log" \ | grep -v -P '^(?!lib/).+: missing-(\w+-)?docstring ' \ | grep -v ": redefined-builtin \\[.*\\] Redefining built-in 'input'" \ | grep -v -P "^tests/.+: wrong-import-order \\[.*\\] external import \"import lib[.].+\" comes before \"from . import tools\"" \ | LC_ALL=C sort -k2 \ | grep '.' || exit 1 rm "$log" # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/private/tags-as-rst0000755000000000000000000000424513733665553017410 0ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright © 2012-2020 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 re import sys sys.path[0] += '/..' from lib import tags as tagmod 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: match = re.match(r'\A(?P[\w-]+)[(](?P
[0-9])[)]\Z', ref) if match is not None: ref = r'**{name}**\ ({section})'.format_map(match.groupdict()) print(' |', ref) print() print('Severity, certainty:', end='\n\n') print(' {}, {}'.format(tag.severity.name, tag.certainty.name)) print() def main(): sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='UTF-8') output_tags_rst(tagmod.iter_tags()) if __name__ == '__main__': main() # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/private/update-blackbox-tests0000755000000000000000000000325513733665553021450 0ustar00rootroot00000000000000#!/usr/bin/env 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 sts=4 sw=4 et i18nspector-0.26/private/update-branch-coverage0000755000000000000000000000443013733665553021545 0ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright © 2014-2018 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(): os.chdir(basedir) module_glob = os.path.join('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' ) plugin = Coverage() report_stream = plugin.stream = io.StringIO() print('Generated automatically by private/update-branch-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 sts=4 sw=4 et i18nspector-0.26/private/update-charmaps0000755000000000000000000000447313733665553020324 0ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright © 2013-2016 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 sys # pylint: disable=wrong-import-position sys.path[0] += '/..' basedir = sys.path[0] 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(): # pylint: disable=protected-access for encoding, codec in encodings._portable_encodings.items(): if codec is None: generate_charmap(encoding) for encoding in encodings._extra_encodings: generate_charmap(encoding) # pylint: enable=protected-access if __name__ == '__main__': main() # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/private/update-header-fields0000755000000000000000000000517513733665553021222 0ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright © 2012-2016 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 import tempfile xgettexts = {'xgettext', 'pygettext'} def main(): os.environ['LC_ALL'] = 'C' xgettext_versions = { ipc.check_output([xgettext, '--version']).splitlines()[0].decode('ASCII', 'replace') for xgettext in xgettexts } with tempfile.TemporaryDirectory(prefix='i18nspector.private.') as tmpdir: 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 } 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 sts=4 sw=4 et i18nspector-0.26/private/update-iso-codes0000755000000000000000000001163113733665553020405 0ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright © 2012-2016 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 json 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/iso-codes/json'.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 load_json(path): with open(path, 'rt', encoding='UTF-8') as file: return json.load(file) def generate_iso_639(): # ======================= # ISO 639: language codes # ======================= l2t_to_2b = {} iso_639 = {} data = load_json(get_iso_codes_dir() + '/iso_639-2.json') for item in data['639-2']: l2t = item['alpha_3'] l2b = item.get('bibliographic', l2t) 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 = {} data = load_json(get_iso_codes_dir() + '/iso_639-3.json') for item in data['639-3']: code = item['alpha_3'] if len(code) != 3: raise Panic('len({!r}) != 3'.format(code)) code1 = item.get('alpha_2') code2 = item.get('terminology') 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 = item['scope'] if scope == 'S': # Not a real language, ignore. continue elif scope in {'M', 'I'}: pass else: raise Panic('unknown scope: {!r}'.format(scope)) reference_name = item['name'] if reference_name in iso_639: raise Panic('duplicate reference name: {!r}'.format(reference_name)) 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() data = load_json(get_iso_codes_dir() + '/iso_3166-1.json') for item in data['3166-1']: cc = item['alpha_2'] 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 sts=4 sw=4 et i18nspector-0.26/private/update-tag-coverage0000755000000000000000000000377513733665553021076 0ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright © 2012-2018 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 sys.path[0] += '/..' 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' ) 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: unknown tag {tag}'.format(tag=tag), file=sys.stderr) rc = 1 sys.exit(rc) if __name__ == '__main__': main() # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/private/update-timezones0000755000000000000000000000632313733665553020537 0ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright © 2013-2016 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 subprocess as ipc import sys import pytz # pylint: disable=wrong-import-position sys.path[0] += '/..' basedir = sys.path[0] from lib import gettext def get_tzdata_version(): version = pytz.OLSON_VERSION if os.path.exists('/etc/debian_version'): # On Debian systems, pytz uses the system timezone database, # so pytz.OLSON_VERSION is not reliable. version = ipc.check_output(['dpkg-query', '-Wf', '${Version}', 'tzdata']) version = version.decode('ASCII') version, revision = version.rsplit('-', 1) del revision return version 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) # pylint: disable=protected-access 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. # Timezone database version: {version} # Last update: {today} '''.format( version=get_tzdata_version(), 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 sts=4 sw=4 et i18nspector-0.26/private/update-version0000755000000000000000000000040713733665553020204 0ustar00rootroot00000000000000#!/bin/sh version=${1:?"no version number provided"} set -e -x dch -m -v "$version" -u low -c doc/changelog export version perl -pi -e 's/^__version__ = '"'"'\K[\w.]+/$ENV{version}/' lib/*.py perl -pi -e 's/^:version: \S+ \K[\w.]+/$ENV{version}/' doc/manpage.rst i18nspector-0.26/tests/0000755000000000000000000000000013733665553015000 5ustar00rootroot00000000000000i18nspector-0.26/tests/__init__.py0000644000000000000000000000004513733665553017110 0ustar00rootroot00000000000000type(...) # Python >= 3 is required i18nspector-0.26/tests/blackbox_tests/0000755000000000000000000000000013733665553020007 5ustar00rootroot00000000000000i18nspector-0.26/tests/blackbox_tests/__init__.py0000644000000000000000000003014513733665553022123 0ustar00rootroot00000000000000# Copyright © 2012-2017 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 inspect import io import multiprocessing as mp import os import re import shlex import signal import subprocess as ipc import sys import traceback import unittest import nose import nose.plugins from .. import tools here = os.path.dirname(__file__) # ---------------------------------------- def this(): ''' Return function that called this function. (Hopefully!) ''' return globals()[inspect.stack()[1][0].f_code.co_name] # ---------------------------------------- _parse_etag = re.compile(r'([A-Z]): (([\w-]+).*)').match def parse_etag(contents, path): 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(): _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): if self.wantFile(path): yield TestCase(path) def wantFunction(self, func): if getattr(func, 'redundant', False): return False class TestCase(unittest.TestCase): def __init__(self, path): super().__init__('_test') self.path = os.path.relpath(path) def _test(self): _test_file(self.path, basedir=None) def __str__(self): return self.path class SubprocessError(Exception): pass def queue_get(queue, process): ''' Remove and return an item from the queue. Block until the process terminates. ''' while True: try: return queue.get(timeout=1) # This semi-active waiting is ugly, but there doesn't seem be any # obvious better way. except mp.queues.Empty: if process.exitcode is None: continue else: raise def run_i18nspector(options, path): commandline = os.environ.get('I18NSPECTOR_COMMANDLINE') if commandline is None: # We cheat here a bit, because exec(3)ing is very expensive. # Let's load the needed Python modules, and use multiprocessing to # “emulate” the command execution. import lib.cli # pylint: disable=import-outside-toplevel assert lib.cli # make pyflakes happy prog = os.path.join(here, os.pardir, os.pardir, 'i18nspector') commandline = [sys.executable, prog] queue = mp.Queue() child = mp.Process( target=_mp_run_i18nspector, args=(prog, options, path, queue) ) child.start() [stdout, stderr] = ( s.splitlines() for s in queue_get(queue, child) ) child.join() rc = child.exitcode else: commandline = shlex.split(commandline) commandline += options commandline += [path] fixed_env = dict(os.environ, PYTHONIOENCODING='UTF-8') child = ipc.Popen(commandline, stdout=ipc.PIPE, stderr=ipc.PIPE, env=fixed_env) stdout, stderr = ( s.decode('UTF-8').splitlines() for s in child.communicate() ) rc = child.poll() assert isinstance(rc, int) if rc == 0: return stdout if rc < 0: message = ['command was interrupted by signal {sig}'.format(sig=get_signal_name(-rc))] # pylint: disable=invalid-unary-operand-type 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 SubprocessError('\n'.join(message)) def _mp_run_i18nspector(prog, options, path, queue): with open(prog, 'rt', encoding='UTF-8') as file: code = file.read() sys.argv = [prog] + list(options) + [path] orig_stdout = sys.stdout orig_stderr = sys.stderr code = compile(code, prog, 'exec') io_stdout = io.StringIO() io_stderr = io.StringIO() gvars = dict( __file__=prog, ) (sys.stdout, sys.stderr) = (io_stdout, io_stderr) try: try: exec(code, gvars) # pylint: disable=exec-used finally: (sys.stdout, sys.stderr) = (orig_stdout, orig_stderr) stdout = io_stdout.getvalue() stderr = io_stderr.getvalue() except SystemExit: queue.put([stdout, stderr]) raise except: # pylint: disable=bare-except exctp, exc, tb = sys.exc_info() stderr += ''.join( traceback.format_exception(exctp, exc, tb) ) queue.put([stdout, stderr]) sys.exit(1) raise # hi, pydiatra! else: queue.put([stdout, stderr]) sys.exit(0) def assert_emit_tags(path, etags, *, options=()): etags = list(etags) stdout = run_i18nspector(options, path) 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='UTF-8') except FileNotFoundError: pass else: with file: return _parse_test_header_file(file, path, comments_only=False) # .gen: try: file = open(path + '.gen', encoding='UTF-8', errors='ignore') except FileNotFoundError: pass else: with file: return _parse_test_header_file(file, path, comments_only=True) # : with open(path, 'rt', encoding='UTF-8', errors='ignore') as file: return _parse_test_header_file(file, path, comments_only=True) def _test_file(path, basedir=here): if basedir is not None: path = os.path.relpath(os.path.join(basedir, 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) del options 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): del dirnames 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 test_file.redundant = True # not needed if the plugin is enabled @tagstring(''' E: os-error No such file or directory ''') def test_os_error_no_such_file(): with tools.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 tools.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 sts=4 sw=4 et i18nspector-0.26/tests/blackbox_tests/ancient-po-revision-date.po0000644000000000000000000000110213733665553025145 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.26/tests/blackbox_tests/ancient-pot-creation-date.po0000644000000000000000000000110313733665553025300 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.26/tests/blackbox_tests/boilerplate-in-content-type.po0000644000000000000000000000110713733665553025703 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.26/tests/blackbox_tests/boilerplate-in-initial-comments.po0000644000000000000000000000140113733665553026523 0ustar00rootroot00000000000000# Polish translations for PACKAGE package # Polskie tłumaczenia dla pakietu PACKAGE. # Copyright (C) 2015 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Jakub Wilk , 2015. # 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.26/tests/blackbox_tests/boilerplate-in-initial-comments.po.tags0000644000000000000000000000042113733665553027461 0ustar00rootroot00000000000000I: boilerplate-in-initial-comments 'Polish translations for PACKAGE package' I: boilerplate-in-initial-comments "Copyright (C) 2015 THE PACKAGE'S COPYRIGHT HOLDER" I: boilerplate-in-initial-comments 'This file is distributed under the same license as the PACKAGE package.' i18nspector-0.26/tests/blackbox_tests/boilerplate-in-initial-comments.pot0000644000000000000000000000123613733665553026715 0ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, 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.26/tests/blackbox_tests/boilerplate-in-initial-comments.pot.tags0000644000000000000000000000030413733665553027645 0ustar00rootroot00000000000000I: boilerplate-in-initial-comments "Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER" I: boilerplate-in-initial-comments 'This file is distributed under the same license as the PACKAGE package.' i18nspector-0.26/tests/blackbox_tests/boilerplate-in-language-team.po0000644000000000000000000000110213733665553025754 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.26/tests/blackbox_tests/boilerplate-in-last-translator.po0000644000000000000000000000100213733665553026376 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: 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.26/tests/blackbox_tests/boilerplate-in-last-translator.po.tags0000644000000000000000000000007613733665553027345 0ustar00rootroot00000000000000W: boilerplate-in-last-translator 'FULL NAME ' i18nspector-0.26/tests/blackbox_tests/boilerplate-in-po-revision-date.po0000644000000000000000000000111113733665553026432 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.26/tests/blackbox_tests/boilerplate-in-pot-creation-date.po0000644000000000000000000000111213733665553026565 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.26/tests/blackbox_tests/boilerplate-in-project-id-version-1.po0000644000000000000000000000107413733665553027136 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.26/tests/blackbox_tests/boilerplate-in-project-id-version-2.po0000644000000000000000000000107413733665553027137 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.26/tests/blackbox_tests/boilerplate-in-report-msgid-bugs.po0000644000000000000000000000100713733665553026623 0ustar00rootroot00000000000000msgid "" 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.26/tests/blackbox_tests/boilerplate-in-report-msgid-bugs.po.tags0000644000000000000000000000010313733665553027554 0ustar00rootroot00000000000000W: boilerplate-in-report-msgid-bugs-to 'FULL NAME ' i18nspector-0.26/tests/blackbox_tests/bom-in-translation.po0000644000000000000000000000120413733665553024061 0ustar00rootroot00000000000000# E: unusual-character-in-translation msgid 'A quick brown fox jumps over the lazy dog.': U+FEFF ZERO WIDTH NO-BREAK SPACE 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.26/tests/blackbox_tests/broken-encoding-and-syntax-error.po0000644000000000000000000000120013733665553026617 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.26/tests/blackbox_tests/broken-encoding-due-to-missing-content-type.po0000644000000000000000000000116413733665553030706 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.26/tests/blackbox_tests/broken-encoding.po0000644000000000000000000000112413733665553023411 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.26/tests/blackbox_tests/c-format-string-argument-mixture.po0000644000000000000000000000123013733665553026672 0ustar00rootroot00000000000000# E: c-format-string-error msgid 'A quick brown %s jumps over the lazy %s.': mixed numbered and unnumbered argument specifications '%1$d' 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 msgid "A quick brown %s jumps over the lazy %s." msgstr "Sic fugiens, %s, zelotypos, quam %1$d haberis." i18nspector-0.26/tests/blackbox_tests/c-format-string-argument-range-error.po0000644000000000000000000000121213733665553027420 0ustar00rootroot00000000000000# E: c-format-string-error msgid 'A quick brown %s jumps over the lazy %s.': argument index too small or too large '%0$s' 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 msgid "A quick brown %s jumps over the lazy %s." msgstr "Sic fugiens, %0$s, zelotypos, quam %1$d haberis." i18nspector-0.26/tests/blackbox_tests/c-format-string-argument-type-mismatch-1.po0000644000000000000000000000122413733665553030122 0ustar00rootroot00000000000000# E: c-format-string-argument-type-mismatch msgid 'A quick brown %s jumps over the lazy dog.': int (msgstr) != const char * (msgid) 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 msgid "A quick brown %s jumps over the lazy dog." msgstr "Sic fugiens, %d, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/c-format-string-argument-type-mismatch-2.po0000644000000000000000000000210213733665553030117 0ustar00rootroot00000000000000# E: c-format-string-argument-type-mismatch msgid '%d quick brown fox jumps over the lazy dog.': short int (msgstr[0]) != int (msgid) # E: c-format-string-argument-type-mismatch msgid '%d quick brown fox jumps over the lazy dog.': long int (msgstr[2]) != int (msgid_plural) 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" #, c-format 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 %hd 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 %ld flag." i18nspector-0.26/tests/blackbox_tests/c-format-string-argument-type-mismatch.pot0000644000000000000000000000137013733665553030152 0ustar00rootroot00000000000000# E: c-format-string-argument-type-mismatch msgid '%d quick brown fox jumps over the lazy dog.': int (msgid) != long int (msgid_plural) #, 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, c-format msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%ld quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/c-format-string-duplicate-flag.po0000644000000000000000000000120313733665553026236 0ustar00rootroot00000000000000# P: c-format-string-redundant-flag msgid 'A quick brown %--s jumps over the lazy dog.': duplicate - in '%--s' 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 msgid "A quick brown %--s jumps over the lazy dog." msgstr "Sic fugiens, %--s, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/c-format-string-error-argument-type-mismatch.po0000644000000000000000000000122113733665553031110 0ustar00rootroot00000000000000# E: c-format-string-error msgid 'A quick brown %1$s jumps over the lazy %1$s.': argument type mismatch 1$ const char *, int 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 msgid "A quick brown %1$s jumps over the lazy %1$s." msgstr "Sic fugiens, %1$s, zelotypos, quam %1$d haberis." i18nspector-0.26/tests/blackbox_tests/c-format-string-error-missing-argument.po0000644000000000000000000000116013733665553027777 0ustar00rootroot00000000000000# E: c-format-string-error msgid 'A quick brown %s jumps over the lazy %s.': missing argument 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" #, c-format msgid "A quick brown %s jumps over the lazy %s." msgstr "Sic fugiens, dux, zelotypos, quam %2$s haberis." i18nspector-0.26/tests/blackbox_tests/c-format-string-error.po0000644000000000000000000000120613733665553024511 0ustar00rootroot00000000000000# E: c-format-string-error msgid 'A quick brown fox jumps over the lazy dog.': invalid conversion specification '%' 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 msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis%" i18nspector-0.26/tests/blackbox_tests/c-format-string-excess-arguments-1.po0000644000000000000000000000117513733665553027020 0ustar00rootroot00000000000000# E: c-format-string-excess-arguments msgid 'A quick brown %s jumps over the lazy dog.': 2 (msgstr) > 1 (msgid) 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 msgid "A quick brown %s jumps over the lazy dog." msgstr "Sic fugiens, %s, zelotypos, quam %s haberis." i18nspector-0.26/tests/blackbox_tests/c-format-string-excess-arguments-2.po0000644000000000000000000000204313733665553027014 0ustar00rootroot00000000000000# E: c-format-string-excess-arguments msgid '%d quick brown fox jumps over the lazy dog.': 2 (msgstr[0]) > 1 (msgid) # E: c-format-string-excess-arguments msgid '%d quick brown fox jumps over the lazy dog.': 2 (msgstr[2]) > 1 (msgid_plural) 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" #, c-format 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ń %2$s twój i %1$d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %1$d flagi." msgstr[2] "Mężny bądź, chroń %2$s twój i %1$d flag." i18nspector-0.26/tests/blackbox_tests/c-format-string-excess-arguments.pot0000644000000000000000000000134413733665553027044 0ustar00rootroot00000000000000# E: c-format-string-excess-arguments msgid '%d quick brown fox jumps over the lazy dog.': 1 (msgid) > 0 (msgid_plural) #, 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, c-format msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "Quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/c-format-string-flag-error.po0000644000000000000000000000121513733665553025420 0ustar00rootroot00000000000000# E: c-format-string-error msgid 'A quick brown %s jumps over the lazy dog.': unexpected format flag character '#' in '%#s' 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 msgid "A quick brown %s jumps over the lazy dog." msgstr "Sic fugiens, %#s, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/c-format-string-forbidden-argument-index.po0000644000000000000000000000122313733665553030240 0ustar00rootroot00000000000000# E: c-format-string-error msgid '100%% of quick brown foxes jump over the lazy %s.': argument index not allowed '%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" #, c-format msgid "100%% of quick brown foxes jump over the lazy %s." msgstr "Mężny bądź, chroń %2$s twój i 100%1$% flag." i18nspector-0.26/tests/blackbox_tests/c-format-string-length-error.po0000644000000000000000000000117513733665553025775 0ustar00rootroot00000000000000# E: c-format-string-error msgid 'A quick brown %s jumps over the lazy dog.': invalid length modifier '%hs' 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 msgid "A quick brown %s jumps over the lazy dog." msgstr "Sic fugiens, %hs, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/c-format-string-missing-argument.po0000644000000000000000000000116013733665553026650 0ustar00rootroot00000000000000# E: c-format-string-error msgid 'A quick brown %s jumps over the lazy %s.': missing argument 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" #, c-format msgid "A quick brown %s jumps over the lazy %s." msgstr "Sic fugiens, dux, zelotypos, quam %2$s haberis." i18nspector-0.26/tests/blackbox_tests/c-format-string-missing-non-numeral.po0000644000000000000000000000165113733665553027266 0ustar00rootroot00000000000000# E: c-format-string-missing-arguments msgid '%s quick brown fox jumps over the lazy dog.': 0 (msgstr[0]) < 1 (msgid) 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" #, c-format msgid "%s quick brown fox jumps over the lazy dog." msgid_plural "%s quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %s flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %s flag." i18nspector-0.26/tests/blackbox_tests/c-format-string-missing-non-numeral.pot0000644000000000000000000000134613733665553027453 0ustar00rootroot00000000000000# E: c-format-string-missing-arguments msgid 'A quick brown fox jumps over the lazy dog.': 0 (msgid) < 1 (msgid_plural) #, 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, c-format msgid "A quick brown fox jumps over the lazy dog." msgid_plural "%s quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/c-format-string-missing-numeral.po0000644000000000000000000000132413733665553026473 0ustar00rootroot00000000000000# E: c-format-string-missing-arguments msgid once: 0 (msgstr[0]) < 1 (msgid_plural) 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: Russian \n" "Language: ru\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%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n" #, c-format msgid "once" msgid_plural "%d times" msgstr[0] "paз" msgstr[1] "%d paзи" msgstr[2] "%d paзiв" i18nspector-0.26/tests/blackbox_tests/c-format-string-msgid-error.po0000644000000000000000000000102113733665553025605 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" #, c-format msgid "A quick brown fox jumps over the lazy dog%" msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis%" i18nspector-0.26/tests/blackbox_tests/c-format-string-msgid-error.pot0000644000000000000000000000113713733665553026001 0ustar00rootroot00000000000000# E: c-format-string-error msgid 'A quick brown fox jumps over the lazy dog%': invalid conversion specification '%' #, 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" #, c-format msgid "A quick brown fox jumps over the lazy dog%" msgstr "" i18nspector-0.26/tests/blackbox_tests/c-format-string-no-excess-arguments.po0000644000000000000000000000120213733665553027263 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: Russian \n" "Language: ru\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%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n" #, c-format msgid "once" msgid_plural "%d times" msgstr[0] "%d paз" msgstr[1] "%d paзи" msgstr[2] "%d paзiв" i18nspector-0.26/tests/blackbox_tests/c-format-string-non-portable-conversion.po0000644000000000000000000000143313733665553030145 0ustar00rootroot00000000000000# P: c-format-string-non-portable-conversion msgid '%zd%% of quick brown foxes jump over the lazy %S.': '%S' => '%ls' in '%2$S' # P: c-format-string-non-portable-conversion msgid '%zd%% of quick brown foxes jump over the lazy %S.': '%Zd' => '%zd' in '%1$Zd' 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" #, c-format msgid "%zd%% of quick brown foxes jump over the lazy %S." msgstr "Mężny bądź, chroń %2$S twój i %1$Zd flag." i18nspector-0.26/tests/blackbox_tests/c-format-string-non-portable-conversion.pot0000644000000000000000000000152713733665553030335 0ustar00rootroot00000000000000# P: c-format-string-non-portable-conversion msgid '%Ld quick brown fox jumps over the lazy dog.': '%Ld' => '%lld' # P: c-format-string-non-portable-conversion msgid '%Ld quick brown fox jumps over the lazy dog.': '%qd' => '%lld' #, 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, c-format msgid "%Ld quick brown fox jumps over the lazy dog." msgid_plural "%qd quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/c-format-string-okay.po0000644000000000000000000000101713733665553024323 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" #, c-format msgid "A quick brown %s jumps over the lazy dog." msgstr "Sic fugiens, %s, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/c-format-string-okay.pot0000644000000000000000000000075113733665553024513 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" #, c-format msgid "A quick brown %s jumps over the lazy dog." msgstr "" i18nspector-0.26/tests/blackbox_tests/c-format-string-omitted-numeral-1.po0000644000000000000000000000146213733665553026630 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" #, c-format 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 jedną 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.26/tests/blackbox_tests/c-format-string-omitted-numeral-2.po0000644000000000000000000000146113733665553026630 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" #, c-format msgid "A 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 jedną 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.26/tests/blackbox_tests/c-format-string-omitted-numeral-5.po0000644000000000000000000000277213733665553026641 0ustar00rootroot00000000000000# E: c-format-string-missing-arguments msgid 'A quick brown fox jumps over the lazy dog.' msgctxt 'max 6': 0 (msgstr[2]) < 1 (msgid_plural) 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" # %d doesn't have to be included in msgstr[2], because according to the range # flag, it applies only to n=5. #, c-format, range: 1..5 msgctxt "max 5" msgid "A 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 jedną 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 pięć flag." # %d cannot be omitted in msgstr[2], because it applies not only to n=5 but # also n=6. #, c-format, range: 1..6 msgctxt "max 6" msgid "A 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 jedną 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 pięć flag." i18nspector-0.26/tests/blackbox_tests/c-format-string-omitted-numeral.pot0000644000000000000000000000115513733665553026655 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, c-format msgid "A 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.26/tests/blackbox_tests/c-format-string-overridden-flag-1.po0000644000000000000000000000123213733665553026565 0ustar00rootroot00000000000000# P: c-format-string-redundant-flag msgid '%d%% of quick brown foxes jump over the lazy dog.': '+' overridden by ' ' in '%+ d' 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" #, c-format msgid "%d%% of quick brown foxes jump over the lazy dog." msgstr "Mężny bądź, chroń pułk twój i %+ d%% flag." i18nspector-0.26/tests/blackbox_tests/c-format-string-overridden-flag-2.po0000644000000000000000000000121013733665553026562 0ustar00rootroot00000000000000# P: c-format-string-redundant-flag msgid '%d%% of quick brown foxes jump over the lazy dog.': 0 in '%0.3d' 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" #, c-format msgid "%d%% of quick brown foxes jump over the lazy dog." msgstr "Mężny bądź, chroń pułk twój i %0.3d%% flag." i18nspector-0.26/tests/blackbox_tests/c-format-string-plural-okay.po0000644000000000000000000000145513733665553025626 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" #, c-format 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.26/tests/blackbox_tests/c-format-string-plural-okay.pot0000644000000000000000000000115613733665553026010 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, c-format 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.26/tests/blackbox_tests/c-format-string-precision-error.po0000644000000000000000000000121213733665553026477 0ustar00rootroot00000000000000# E: c-format-string-error msgid 'A quick brown fox jumps over the lazy dog%.42s': unexpected precision '%.42c' 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 msgid "A quick brown fox jumps over the lazy dog%.42s" msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis%.42c" i18nspector-0.26/tests/blackbox_tests/c-format-string-precision-range-error.po0000644000000000000000000000121513733665553027574 0ustar00rootroot00000000000000# E: c-format-string-error msgid 'A quick brown %s jumps over the lazy dog.': precision too large '%.9999999999s' 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 msgid "A quick brown %s jumps over the lazy dog." msgstr "Sic fugiens, %.9999999999s, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/c-format-string-width-error.po0000644000000000000000000000117613733665553025634 0ustar00rootroot00000000000000# E: c-format-string-error msgid 'A quick brown %s jumps over the lazy dog.%n': unexpected width '%24n' 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 msgid "A quick brown %s jumps over the lazy dog.%n" msgstr "Sic fugiens, %s, zelotypos, quam Karus haberis.%24n" i18nspector-0.26/tests/blackbox_tests/c-format-string-width-range-error.po0000644000000000000000000000121513733665553026720 0ustar00rootroot00000000000000# E: c-format-string-error msgid 'A quick brown %s jumps over the lazy dog.': field width too large '%9999999999s' 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 msgid "A quick brown %s jumps over the lazy dog." msgstr "Sic fugiens, %9999999999s, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/c0-control-characters.po0000644000000000000000000000120113733665553024436 0ustar00rootroot00000000000000# E: unusual-character-in-translation msgid 'A quick brown fox jumps over the lazy dog.': U+0019 control character EM 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.26/tests/blackbox_tests/c1-control-characters.po0000644000000000000000000000120413733665553024442 0ustar00rootroot00000000000000# E: unusual-character-in-translation msgid 'A quick brown fox jumps over the lazy dog.': U+0080 control character PAD 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.26/tests/blackbox_tests/codomain-error-in-plural-forms-1.po0000644000000000000000000000230013733665553026445 0ustar00rootroot00000000000000# E: unusual-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.26/tests/blackbox_tests/codomain-error-in-plural-forms-1a.po0000644000000000000000000000237113733665553026616 0ustar00rootroot00000000000000# E: unusual-plural-forms 'nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);' => '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) != 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=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 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." msgstr[3] "Mężny bądź, chroń pułk twój i %d flag." i18nspector-0.26/tests/blackbox_tests/codomain-error-in-plural-forms-2.po0000644000000000000000000000152413733665553026455 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.26/tests/blackbox_tests/codomain-error-in-unused-plural-forms.po0000644000000000000000000000134113733665553027614 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.26/tests/blackbox_tests/conflict-marker-in-fuzzy-translation.po0000644000000000000000000000143313733665553027555 0ustar00rootroot00000000000000# conflict-marker-in-translation should not trigger for fuzzy entries. # https://bugs.debian.org/753924 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" #, fuzzy 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.26/tests/blackbox_tests/conflict-marker-in-header-entry-1.po0000644000000000000000000000122313733665553026554 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.26/tests/blackbox_tests/conflict-marker-in-header-entry-2.po0000644000000000000000000000122313733665553026555 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.26/tests/blackbox_tests/conflict-marker-in-translation.po0000644000000000000000000000146413733665553026374 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.26/tests/blackbox_tests/conflicting-format-flags-1.po0000644000000000000000000000120713733665553025364 0ustar00rootroot00000000000000# E: conflicting-message-flags msgid 'A quick brown fox jumps over the lazy dog.': c-format lisp-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, lisp-format msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/conflicting-format-flags-2.po0000644000000000000000000000120713733665553025365 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.26/tests/blackbox_tests/conflicting-format-flags-3.po0000644000000000000000000000122713733665553025370 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.26/tests/blackbox_tests/conflicting-format-flags-4.po0000644000000000000000000000125113733665553025366 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.26/tests/blackbox_tests/conflicting-message-flags.po0000644000000000000000000000116713733665553025367 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.26/tests/blackbox_tests/coverage0000644000000000000000000001005013733665553021521 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-initial-comments [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] c-format-string-argument-type-mismatch [X] c-format-string-error [X] c-format-string-excess-arguments [X] c-format-string-missing-arguments [X] c-format-string-non-portable-conversion [X] c-format-string-redundant-flag [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] 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] leading-junk-in-plural-forms [X] malformed-xml [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] partially-translated-message [X] python-brace-format-string-argument-type-mismatch [X] python-brace-format-string-error [X] python-brace-format-string-missing-argument [X] python-brace-format-string-unknown-argument [X] python-format-string-argument-number-mismatch [X] python-format-string-argument-type-mismatch [X] python-format-string-error [X] python-format-string-missing-argument [X] python-format-string-multiple-unnamed-arguments [X] python-format-string-obsolete-conversion [X] python-format-string-redundant-flag [X] python-format-string-redundant-length [X] python-format-string-redundant-precision [X] python-format-string-unknown-argument [X] python-format-string-unnamed-plural-argument [X] qt-plural-format-mistaken-for-c-format [X] range-flag-without-plural-string [X] redundant-message-flag [X] stray-header-line [X] stray-previous-msgid [X] syntax-error-in-plural-forms [X] syntax-error-in-po-file [X] syntax-error-in-unused-plural-forms [X] trailing-junk-in-plural-forms [X] translation-in-template [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 [X] unusual-plural-forms [X] unusual-unused-plural-forms i18nspector-0.26/tests/blackbox_tests/crlf.po0000644000000000000000000000102413733665553021272 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.26/tests/blackbox_tests/distant-header-entry.po0000644000000000000000000000104013733665553024375 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.26/tests/blackbox_tests/dotless-domain-in-language-team.po0000644000000000000000000000105713733665553026405 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.26/tests/blackbox_tests/dotless-domain-in-last-translator.po0000644000000000000000000000106613733665553027030 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.26/tests/blackbox_tests/dotless-domain-in-report-msgid-bugs-to.po0000644000000000000000000000106613733665553027670 0ustar00rootroot00000000000000# W: invalid-report-msgid-bugs-to 'gizmoenhancer@net' msgid "" msgstr "" "Project-Id-Version: Gizmo Enhancer 1.0\n" "Report-Msgid-Bugs-To: gizmoenhancer@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.26/tests/blackbox_tests/duplicate-empty-flag.po0000644000000000000000000000116413733665553024366 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.26/tests/blackbox_tests/duplicate-flag-for-header-entry.pot0000644000000000000000000000102113733665553026557 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: 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.26/tests/blackbox_tests/duplicate-header-entry.po0000644000000000000000000000167213733665553024714 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.26/tests/blackbox_tests/duplicate-header-field-content-transfer-encoding.po0000644000000000000000000000114013733665553031702 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.26/tests/blackbox_tests/duplicate-header-field-content-type.po0000644000000000000000000000113313733665553027255 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.26/tests/blackbox_tests/duplicate-header-field-language-team.po0000644000000000000000000000112513733665553027334 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.26/tests/blackbox_tests/duplicate-header-field-language.po0000644000000000000000000000107413733665553026413 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.26/tests/blackbox_tests/duplicate-header-field-last-translator.po0000644000000000000000000000114413733665553027760 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.26/tests/blackbox_tests/duplicate-header-field-mime-version.po0000644000000000000000000000110513733665553027235 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.26/tests/blackbox_tests/duplicate-header-field-plural-forms.po0000644000000000000000000000166213733665553027256 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.26/tests/blackbox_tests/duplicate-header-field-po-revision-date.po0000644000000000000000000000114413733665553030013 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.26/tests/blackbox_tests/duplicate-header-field-pot-creation-date.po0000644000000000000000000000114613733665553030147 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.26/tests/blackbox_tests/duplicate-header-field-project-id-version.po0000644000000000000000000000114013733665553030345 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.26/tests/blackbox_tests/duplicate-header-field-report-msgid-bugs-to.po0000644000000000000000000000115113733665553030616 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.26/tests/blackbox_tests/duplicate-header-field-x-poedit-country.po0000644000000000000000000000116613733665553030064 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.26/tests/blackbox_tests/duplicate-header-field-x-poedit-language.po0000644000000000000000000000116713733665553030145 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.26/tests/blackbox_tests/duplicate-header-field.po0000644000000000000000000000114313733665553024627 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.26/tests/blackbox_tests/duplicate-message-definition-with-context.po0000644000000000000000000000136713733665553030533 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.26/tests/blackbox_tests/duplicate-message-definition.po0000644000000000000000000000131113733665553026065 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.26/tests/blackbox_tests/duplicate-message-flag.po0000644000000000000000000000117613733665553024657 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.26/tests/blackbox_tests/empty-content-transfer-encoding.po0000644000000000000000000000110013733665553026553 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.26/tests/blackbox_tests/empty-content-type.po0000644000000000000000000000107213733665553024134 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.26/tests/blackbox_tests/empty-file.po0000644000000000000000000000065113733665553022424 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.26/tests/blackbox_tests/empty-file.pot0000644000000000000000000000066113733665553022611 0ustar00rootroot00000000000000# W: empty-file #, 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" i18nspector-0.26/tests/blackbox_tests/empty-mime-version.po0000644000000000000000000000106313733665553024115 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.26/tests/blackbox_tests/empty-msgid-message-with-plural-forms.po0000644000000000000000000000157213733665553027627 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.26/tests/blackbox_tests/empty-msgid-message-with-source-code-references.po0000644000000000000000000000112413733665553031524 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.26/tests/blackbox_tests/empty-po-revision-date.po0000644000000000000000000000104413733665553024667 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.26/tests/blackbox_tests/empty-pot-creation-date.po0000644000000000000000000000104513733665553025022 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.26/tests/blackbox_tests/empty-project-id-version.po0000644000000000000000000000114313733665553025225 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.26/tests/blackbox_tests/empty-report-msgid-bugs.po0000644000000000000000000000103113733665553025050 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.26/tests/blackbox_tests/encoding-in-header-field.po0000644000000000000000000000107413733665553025052 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.26/tests/blackbox_tests/escape-sequences.po0000644000000000000000000000115213733665553023577 0ustar00rootroot00000000000000# E: duplicate-message-definition msgid '\x07\x07\x08\x08\x0c\x0c\t\t\x0b\x0b\r…\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.26/tests/blackbox_tests/future-po-revision-date.po0000644000000000000000000000110613733665553025042 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.26/tests/blackbox_tests/future-pot-creation-date.po0000644000000000000000000000110713733665553025175 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.26/tests/blackbox_tests/fuzzy-header-entry.po0000644000000000000000000000104713733665553024125 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.26/tests/blackbox_tests/generated-by-field.po0000644000000000000000000000161713733665553024003 0ustar00rootroot00000000000000# The Generated-By field is not used or generated by any of the GNU # gettext tools. Nevertheless it's rather widespread, as it's used by # pygettext[0] and Babel[1]. Emitting unknown-header-field would be # counter-productive. # # [0] https://docs.python.org/3/library/gettext.html#internationalizing-your-programs-and-modules # [1] http://babel.pocoo.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.26/tests/blackbox_tests/hash-only-comment.po0000644000000000000000000000101413733665553023705 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.26/tests/blackbox_tests/header-entry-flags-splitting.po0000644000000000000000000000114513733665553026044 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.26/tests/blackbox_tests/header-imitation.mo0000644000000000000000000000034713733665553023573 0ustar00rootroot00000000000000,<P*c'0(header imitation)A quick brown fox jumps over the lazy dog.Content-Type: text/plain; charset=UTF-8Sic fugiens, dux, zelotypos, quam Karus haberisi18nspector-0.26/tests/blackbox_tests/header-imitation.mo.gen0000755000000000000000000000116613733665553024346 0ustar00rootroot00000000000000#!/bin/sh # 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 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.26/tests/blackbox_tests/inconsistent-leading-newlines-fuzzy.po0000644000000000000000000000102013733665553027470 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.26/tests/blackbox_tests/inconsistent-leading-newlines.po0000644000000000000000000000114013733665553026306 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.26/tests/blackbox_tests/inconsistent-leading-newlines.pot0000644000000000000000000000127613733665553026504 0ustar00rootroot00000000000000# E: inconsistent-leading-newlines msgid '\n%d quick brown fox jumps over the lazy dog.' #, 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" msgid "\n%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.26/tests/blackbox_tests/inconsistent-number-of-plural-forms.po0000644000000000000000000000234213733665553027401 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.26/tests/blackbox_tests/inconsistent-trailing-newlines-fuzzy.po0000644000000000000000000000102013733665553027676 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.26/tests/blackbox_tests/inconsistent-trailing-newlines.po0000644000000000000000000000113713733665553026522 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.26/tests/blackbox_tests/inconsistent-trailing-newlines.pot0000644000000000000000000000127513733665553026711 0ustar00rootroot00000000000000# E: inconsistent-trailing-newlines msgid '%d quick brown fox jumps over the lazy dog.' #, 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" "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.\n" msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/incorrect-plural-forms.po0000644000000000000000000000147713733665553024771 0ustar00rootroot00000000000000# E: unusual-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.26/tests/blackbox_tests/integer-overflow-in-plural-forms.po0000644000000000000000000000154413733665553026676 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.26/tests/blackbox_tests/integer-overflow-in-unused-plural-forms.po0000644000000000000000000000126613733665553030200 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.26/tests/blackbox_tests/invalid-content-transfer-encoding.po0000644000000000000000000000107413733665553027055 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.26/tests/blackbox_tests/invalid-content-type-with-hint.po0000644000000000000000000000114113733665553026332 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.26/tests/blackbox_tests/invalid-content-type.po0000644000000000000000000000110213733665553024416 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.26/tests/blackbox_tests/invalid-language-corrected.po0000644000000000000000000000104713733665553025530 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.26/tests/blackbox_tests/invalid-language-natural-name.po0000644000000000000000000000105313733665553026137 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.26/tests/blackbox_tests/invalid-language.po0000644000000000000000000000110113733665553023547 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.26/tests/blackbox_tests/invalid-last-translator.po0000644000000000000000000000103613733665553025125 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.26/tests/blackbox_tests/invalid-mime-version.po0000644000000000000000000000105313733665553024404 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.26/tests/blackbox_tests/invalid-mo-file.mo0000644000000000000000000000107113733665553023317 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.26/tests/blackbox_tests/invalid-po-revision-date-with-hint.po0000644000000000000000000000113713733665553027073 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.26/tests/blackbox_tests/invalid-po-revision-date.po0000644000000000000000000000105213733665553025156 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.26/tests/blackbox_tests/invalid-pot-creation-date-with-hint.po0000644000000000000000000000114013733665553027217 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.26/tests/blackbox_tests/invalid-pot-creation-date.po0000644000000000000000000000105313733665553025311 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.26/tests/blackbox_tests/invalid-range-flag-1-element.po0000644000000000000000000000161413733665553025565 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.26/tests/blackbox_tests/invalid-range-flag-empty.po0000644000000000000000000000161413733665553025134 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.26/tests/blackbox_tests/invalid-range-flag-trailing-junk.po0000644000000000000000000000161613733665553026556 0ustar00rootroot00000000000000# E: invalid-range-flag msgid '%d quick brown fox jumps over the lazy dog.': 'range: 1..5x' 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..5x 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.26/tests/blackbox_tests/invalid-range-flag.po0000644000000000000000000000161213733665553023776 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.26/tests/blackbox_tests/invalid-report-msgid-bugs.po0000644000000000000000000000112213733665553025341 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.26/tests/blackbox_tests/language-disparity-command-line.po0000644000000000000000000000113613733665553026502 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.26/tests/blackbox_tests/language-disparity-poedit.po0000644000000000000000000000117513733665553025426 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.26/tests/blackbox_tests/language-team-equal-to-last-translator-2.po0000644000000000000000000000131713733665553030074 0ustar00rootroot00000000000000# W: duplicate-header-field-last-translator # 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" "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.26/tests/blackbox_tests/language-team-equal-to-last-translator.po0000644000000000000000000000116113733665553027732 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.26/tests/blackbox_tests/language-variant-does-affect-translation.po0000644000000000000000000000101213733665553030300 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.26/tests/blackbox_tests/language-variant-does-not-affect-translation.po0000644000000000000000000000110713733665553031103 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.26/tests/blackbox_tests/leading-junk-in-plural-forms.po0000644000000000000000000000154313733665553025747 0ustar00rootroot00000000000000# E: leading-junk-in-plural-forms '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: 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.26/tests/blackbox_tests/lexer-error-in-plural-expression.po0000644000000000000000000000176313733665553026722 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.26/tests/blackbox_tests/lowercase-header-field-name.po0000644000000000000000000000116113733665553025557 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.26/tests/blackbox_tests/message-flags-splitting-1.po0000644000000000000000000000103413733665553025234 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.26/tests/blackbox_tests/message-flags-splitting-2.po0000644000000000000000000000102113733665553025231 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.26/tests/blackbox_tests/multiple-range-flags-1.po0000644000000000000000000000163713733665553024533 0ustar00rootroot00000000000000# W: duplicate-message-flag msgid '%d quick brown fox jumps over the lazy dog.': 'range: 1..05' 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, range: 1..05 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.26/tests/blackbox_tests/multiple-range-flags-2.po0000644000000000000000000000166213733665553024532 0ustar00rootroot00000000000000# E: conflicting-message-flags msgid '%d quick brown fox jumps over the lazy dog.': 'range: 1..5' 'range: 37..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: 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, range: 37..42 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.26/tests/blackbox_tests/multiple-range-flags-3.po0000644000000000000000000000167713733665553024541 0ustar00rootroot00000000000000# E: conflicting-message-flags msgid '%d quick brown fox jumps over the lazy dog.': 'range: 1..5' 'range: 37..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: 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, range: 37..42, 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.26/tests/blackbox_tests/next-line-control-character-in-header-entry.po0000644000000000000000000000112013733665553030645 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.26/tests/blackbox_tests/next-line-control-character-in-translation.po0000644000000000000000000000122013733665553030615 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.26/tests/blackbox_tests/no-content-transfer-encoding.po0000644000000000000000000000106113733665553026037 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.26/tests/blackbox_tests/no-content-type.po0000644000000000000000000000105113733665553023407 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.26/tests/blackbox_tests/no-language-header-field-with-hint.po0000644000000000000000000000106013733665553026761 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.26/tests/blackbox_tests/no-language-header-field.po0000644000000000000000000000106513733665553025055 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.26/tests/blackbox_tests/no-language-team.po0000644000000000000000000000100413733665553023463 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.26/tests/blackbox_tests/no-last-translator.po0000644000000000000000000000077113733665553024120 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.26/tests/blackbox_tests/no-mime-version.po0000644000000000000000000000104413733665553023372 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.26/tests/blackbox_tests/no-package-name-in-project-id-version.po0000644000000000000000000000104613733665553027420 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.26/tests/blackbox_tests/no-plural-forms.po0000644000000000000000000000125213733665553023404 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.26/tests/blackbox_tests/no-plural-forms.pot0000644000000000000000000000116513733665553023573 0ustar00rootroot00000000000000# W: no-plural-forms-header-field 'nplurals=INTEGER; plural=EXPRESSION;' #, 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 "%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.26/tests/blackbox_tests/no-po-revision-date.po0000644000000000000000000000100513733665553024142 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.26/tests/blackbox_tests/no-pot-creation-date.po0000644000000000000000000000100513733665553024274 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.26/tests/blackbox_tests/no-project-id-version.po0000644000000000000000000000100313733665553024476 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.26/tests/blackbox_tests/no-report-msgid-bugs.po0000644000000000000000000000077613733665553024345 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.26/tests/blackbox_tests/no-required-plural-forms.po0000644000000000000000000000147513733665553025231 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.26/tests/blackbox_tests/no-version-in-project-id-version.po0000644000000000000000000000107113733665553026572 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.26/tests/blackbox_tests/non-ascii-compatible.po0000644000000000000000000000105713733665553024347 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.26/tests/blackbox_tests/non-ascii-project-id.po0000644000000000000000000000102213733665553024260 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.26/tests/blackbox_tests/non-portable-encoding-with-hint.po0000644000000000000000000000107713733665553026451 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.26/tests/blackbox_tests/non-portable-encoding.po0000644000000000000000000000106313733665553024533 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.26/tests/blackbox_tests/non-python-encoding.po0000644000000000000000000000111313733665553024240 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.26/tests/blackbox_tests/non-python-portable-encoding.po0000644000000000000000000000075513733665553026061 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.26/tests/blackbox_tests/non-text-encoding.po0000644000000000000000000000105413733665553023707 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.26/tests/blackbox_tests/nonexistent-language.po0000644000000000000000000000110113733665553024477 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.26/tests/blackbox_tests/okay-big-endian.mo0000644000000000000000000000074113733665553023304 0ustar00rootroot00000000000000,<P*Q3|0A quick brown fox jumps over the lazy dog.Project-Id-Version: Gizmo Enhancer 1.0 Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net 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.26/tests/blackbox_tests/okay-big-endian.mo.gen0000755000000000000000000000016613733665553024060 0ustar00rootroot00000000000000#!/bin/sh set -e -u -x exec grep -v '^"POT-Creation-Date: ' "${here}/okay.po"\ | msgfmt --endian=big - -o "${target}" i18nspector-0.26/tests/blackbox_tests/okay-little-endian.mo0000644000000000000000000000074113733665553024040 0ustar00rootroot00000000000000,<P*Q3|0A quick brown fox jumps over the lazy dog.Project-Id-Version: Gizmo Enhancer 1.0 Report-Msgid-Bugs-To: gizmoenhancer@jwilk.net 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.26/tests/blackbox_tests/okay-little-endian.mo.gen0000755000000000000000000000017113733665553024610 0ustar00rootroot00000000000000#!/bin/sh set -e -u -x exec grep -v '^"POT-Creation-Date: ' "${here}/okay.po"\ | msgfmt --endian=little - -o "${target}" i18nspector-0.26/tests/blackbox_tests/okay.po0000644000000000000000000000100513733665553021306 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.26/tests/blackbox_tests/okay.pot0000644000000000000000000000073613733665553021504 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.26/tests/blackbox_tests/partially-translated-message.po0000644000000000000000000000151313733665553026131 0ustar00rootroot00000000000000# E: partially-translated-message 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] "" i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-error.po0000644000000000000000000000123113733665553026301 0ustar00rootroot00000000000000# E: perl-brace-format-string-error msgid 'A quick brown fox jumps over the lazy dog.': invalid placeholder specification '{' 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" #, perl-brace-format msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis{" i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-missing-argument.po0000644000000000000000000000123113733665553030441 0ustar00rootroot00000000000000# E: perl-brace-format-string-missing-argument msgid 'A quick brown {A} jumps over the lazy {B}': A not in msgstr while in msgid 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" #, perl-brace-format msgid "A quick brown {A} jumps over the lazy {B}" msgstr "Sic fugiens, dux, zelotypos, quam {B} haberis." i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-missing-arguments.pot0000644000000000000000000000161013733665553031011 0ustar00rootroot00000000000000# E: perl-brace-format-string-missing-argument msgid 'A quick brown fox jumps over the lazy dog.': N not in msgid while in msgid_plural # E: perl-brace-format-string-missing-argument msgid 'A quick brown fox jumps over the lazy dog.': X not in msgid while in msgid_plural #, 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, perl-brace-format msgid "A quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy {X}." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-missing-numeral.po0000644000000000000000000000136013733665553030265 0ustar00rootroot00000000000000# E: perl-brace-format-string-missing-argument msgid once: N not in msgstr[0] while in msgid_plural 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: Russian \n" "Language: ru\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%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n" #, perl-brace-format msgid "once" msgid_plural "{N} times" msgstr[0] "paз" msgstr[1] "{N} paзи" msgstr[2] "{N} paзiв" i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-msgid-error.po0000644000000000000000000000103213733665553027401 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" #, perl-brace-format msgid "A quick brown fox jumps over the lazy dog{" msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis{" i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-msgid-error.pot0000644000000000000000000000116213733665553027571 0ustar00rootroot00000000000000# E: perl-brace-format-string-error msgid 'A quick brown fox jumps over the lazy dog{': invalid placeholder specification '{' #, 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" #, perl-brace-format msgid "A quick brown fox jumps over the lazy dog{" msgstr "" i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-no-excess-arguments.po0000644000000000000000000000121713733665553031063 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: Russian \n" "Language: ru\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%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n" #, perl-brace-format msgid "once" msgid_plural "{N} times" msgstr[0] "{N} paз" msgstr[1] "{N} paзи" msgstr[2] "{N} paзiв" i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-okay.po0000644000000000000000000000103213733665553026112 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" #, perl-brace-format msgid "A quick brown {X} jumps over the lazy dog." msgstr "Sic fugiens, {X}, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-okay.pot0000644000000000000000000000076313733665553026310 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" #, perl-brace-format msgid "A quick brown {X} jumps over the lazy dog." msgstr "" i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-omitted-numeral-1.po0000644000000000000000000000147713733665553030430 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" #, perl-brace-format msgid "{N} quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi." msgstr[2] "Mężny bądź, chroń pułk twój i {N} flag." i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-omitted-numeral-2.po0000644000000000000000000000147513733665553030427 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" #, perl-brace-format msgid "A quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi." msgstr[2] "Mężny bądź, chroń pułk twój i {N} flag." i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-omitted-numeral-5.po0000644000000000000000000000304213733665553030422 0ustar00rootroot00000000000000# E: perl-brace-format-string-missing-argument msgid 'A quick brown fox jumps over the lazy dog.' msgctxt 'max 6': N not in msgstr[2] while in msgid_plural 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" # {N} doesn't have to be included in msgstr[2], because according to the range # flag, it applies only to n=5. #, perl-brace-format, range: 1..5 msgctxt "max 5" msgid "A quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi." msgstr[2] "Mężny bądź, chroń pułk twój i pięć flag." # {N} cannot be omitted in msgstr[2], because it applies not only to n=5 but # also n=6. #, perl-brace-format, range: 1..6 msgctxt "max 6" msgid "A quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi." msgstr[2] "Mężny bądź, chroń pułk twój i pięć flag." i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-omitted-numeral.pot0000644000000000000000000000116713733665553030452 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, perl-brace-format msgid "A quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-plural-okay.po0000644000000000000000000000147313733665553027420 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" #, perl-brace-format msgid "{N} quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i {N} flagę." msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi." msgstr[2] "Mężny bądź, chroń pułk twój i {N} flag." i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-plural-okay.pot0000644000000000000000000000117113733665553027577 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, perl-brace-format msgid "{N} quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-unknown-argument-1.po0000644000000000000000000000123113733665553030625 0ustar00rootroot00000000000000# E: perl-brace-format-string-unknown-argument msgid 'A quick brown {A} jumps over the lazy dog.': B in msgstr but not in msgid 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" #, perl-brace-format msgid "A quick brown {A} jumps over the lazy dog." msgstr "Sic fugiens, {A}, zelotypos, quam {B} haberis." i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-unknown-argument-2.po0000644000000000000000000000211113733665553030624 0ustar00rootroot00000000000000# E: perl-brace-format-string-unknown-argument msgid '{N} quick brown fox jumps over the lazy dog.': O in msgstr[0] but not in msgid # E: perl-brace-format-string-unknown-argument msgid '{N} quick brown fox jumps over the lazy dog.': O in msgstr[2] but not in msgid_plural 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" #, perl-brace-format msgid "{N} quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń {O} twój i {N} flagę." msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi." msgstr[2] "Mężny bądź, chroń {O} twój i {N} flag." i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-unknown-argument.pot0000644000000000000000000000137613733665553030665 0ustar00rootroot00000000000000# E: perl-brace-format-string-unknown-argument msgid '{N} quick brown fox jumps over the lazy dog.': N in msgid but not in msgid_plural #, 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, perl-brace-format msgid "{N} quick brown fox jumps over the lazy dog." msgid_plural "Quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/plural-forms-okay.po0000644000000000000000000000144113733665553023733 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.26/tests/blackbox_tests/plural-forms-okay.pot0000644000000000000000000000114213733665553024115 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" "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.26/tests/blackbox_tests/plural-forms-without-plural-expression.po0000644000000000000000000000151513733665553030167 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.26/tests/blackbox_tests/po4a-xml-malformed.po0000644000000000000000000000127213733665553023756 0ustar00rootroot00000000000000# E: malformed-xml msgid 'A quick brown fox jumps over the lazy dog.': asynchronous entity: line 1, column 54 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" #. type: Content of: msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/po4a-xml-malformed.pot0000644000000000000000000000121113733665553024133 0ustar00rootroot00000000000000# E: malformed-xml msgid 'A quick brown fox jumps over the lazy dog.': asynchronous entity: line 1, column 48 #, 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=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Content of: msgid "A quick brown fox jumps over the lazy dog." msgstr "" i18nspector-0.26/tests/blackbox_tests/po4a-xml.po0000644000000000000000000000110513733665553022005 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" #. type: Content of: msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/previous-msgid.po0000644000000000000000000000110613733665553023322 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 "The quick brown fox jumps over the lazy dog." msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/publican-dates.po0000644000000000000000000000141613733665553023244 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.26/tests/blackbox_tests/python-brace-format-string-argument-index-too-large.po0000644000000000000000000000124613733665553032353 0ustar00rootroot00000000000000# E: python-brace-format-string-error msgid 'A quick brown {} jumps over the lazy dog.': argument index too large '{9999999999}' 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" #, python-brace-format msgid "A quick brown {} jumps over the lazy dog." msgstr "Sic fugiens, {9999999999}, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-argument-mixture.po0000644000000000000000000000125413733665553031051 0ustar00rootroot00000000000000# E: python-brace-format-string-error msgid 'A quick brown {} jumps over the lazy {}.': mixed numbered and unnumbered argument specifications '{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" #, python-brace-format msgid "A quick brown {} jumps over the lazy {}." msgstr "Sic fugiens, {}, zelotypos, quam {1} haberis." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-argument-number-mismatch-1.po0000644000000000000000000000163513733665553032610 0ustar00rootroot00000000000000# E: python-brace-format-string-unknown-argument msgid 'A quick brown {} jumps over the lazy dog.': 1 in msgstr but not in msgid # E: python-brace-format-string-missing-argument msgid 'A quick brown {} jumps over the lazy {}.': 1 not in msgstr while in msgid 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" #, python-brace-format msgid "A quick brown {} jumps over the lazy dog." msgstr "Sic fugiens, {}, zelotypos, quam {} haberis." #, python-brace-format msgid "A quick brown {} jumps over the lazy {}." msgstr "Sic fugiens, {}, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-argument-number-mismatch-2.po0000644000000000000000000000171513733665553032610 0ustar00rootroot00000000000000# E: python-brace-format-string-unknown-argument msgid '{} quick brown fox jumps over the lazy dog.': 1 in msgstr[2] but not in msgid_plural 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" #, python-brace-format msgid "{} quick brown fox jumps over the lazy dog." msgid_plural "{} quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i {} flagi." msgstr[2] "Mężny bądź, chroń pułk twój i {:{}} flag." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-argument-sorting.po0000644000000000000000000000102613733665553031036 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" #, python-brace-format msgid "A quick brown {} jumps over the lazy {s}." msgstr "Sic fugiens, {}, zelotypos, quam Karus {s}." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-argument-type-mismatch.po0000644000000000000000000000124713733665553032142 0ustar00rootroot00000000000000# E: python-brace-format-string-argument-type-mismatch msgid 'A quick brown {:s} jumps over the lazy dog.': int (msgstr) != str (msgid) 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" #, python-brace-format msgid "A quick brown {:s} jumps over the lazy dog." msgstr "Sic fugiens, {:d}, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-argument-type-mismatch.pot0000644000000000000000000000141613733665553032324 0ustar00rootroot00000000000000# E: python-brace-format-string-argument-type-mismatch msgid '{:s} quick brown fox jumps over the lazy dog.': str (msgid) != int (msgid_plural) #, 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, python-brace-format msgid "{:s} 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.26/tests/blackbox_tests/python-brace-format-string-error-argument-type-mismatch.po0000644000000000000000000000131513733665553033265 0ustar00rootroot00000000000000# E: python-brace-format-string-error msgid 'A quick brown {O:s} jumps over the lazy {O:s}.': argument type mismatch 'Sic fugiens, {O:s}, zelotypos, quam {O:d} 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" #, python-brace-format msgid "A quick brown {O:s} jumps over the lazy {O:s}." msgstr "Sic fugiens, {O:s}, zelotypos, quam {O:d} haberis." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-error.po0000644000000000000000000000124313733665553026663 0ustar00rootroot00000000000000# E: python-brace-format-string-error msgid 'A quick brown fox jumps over the lazy dog.': invalid replacement field specification '}' 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" #, python-brace-format msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis}" i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-invalid-conversion-flag.po0000644000000000000000000000122513733665553032252 0ustar00rootroot00000000000000# E: python-brace-format-string-error msgid 'A quick brown {} jumps over the lazy dog.': invalid conversion flag '{!z}' 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" #, python-brace-format msgid "A quick brown {} jumps over the lazy dog." msgstr "Sic fugiens, {!z}, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-mismatched-conversion-flag.po0000644000000000000000000000127413733665553032746 0ustar00rootroot00000000000000# E: python-brace-format-string-error msgid 'A quick brown {} jumps over the lazy dog.': type mismatch between conversion and format specifications '{!s:d}' 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" #, python-brace-format msgid "A quick brown {} jumps over the lazy dog." msgstr "Sic fugiens, {!s:d}, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-missing-argument.po0000644000000000000000000000224213733665553031023 0ustar00rootroot00000000000000# E: python-brace-format-string-missing-argument msgid 'A quick brown {} jumps over the lazy {}': 1 not in msgstr while in msgid # E: python-brace-format-string-missing-argument msgid 'A quick brown {0} jumps over the lazy {1}': 0 not in msgstr while in msgid # E: python-brace-format-string-missing-argument msgid 'A quick brown {A} jumps over the lazy {B}': A not in msgstr while in msgid 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" #, python-brace-format msgid "A quick brown {} jumps over the lazy {}" msgstr "Sic fugiens, dux, zelotypos, quam {} haberis." #, python-brace-format msgid "A quick brown {0} jumps over the lazy {1}" msgstr "Sic fugiens, dux, zelotypos, quam {1} haberis." #, python-brace-format msgid "A quick brown {A} jumps over the lazy {B}" msgstr "Sic fugiens, dux, zelotypos, quam {B} haberis." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-missing-non-numeral.po0000644000000000000000000000172513733665553031441 0ustar00rootroot00000000000000# E: python-brace-format-string-missing-argument msgid '{N:s} quick brown fox jumps over the lazy dog.': N not in msgstr[0] while in msgid 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" #, python-brace-format msgid "{N:s} quick brown fox jumps over the lazy dog." msgid_plural "{N:s} quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i {N:s} flagi." msgstr[2] "Mężny bądź, chroń pułk twój i {N:s} flag." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-missing-non-numeral.pot0000644000000000000000000000140613733665553031621 0ustar00rootroot00000000000000# E: python-brace-format-string-missing-argument msgid 'A quick brown fox jumps over the lazy dog.': N not in msgid while in msgid_plural #, 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, python-brace-format msgid "A quick brown fox jumps over the lazy dog." msgid_plural "{N:s} quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-missing-numeral.po0000644000000000000000000000136413733665553030650 0ustar00rootroot00000000000000# E: python-brace-format-string-missing-argument msgid once: N not in msgstr[0] while in msgid_plural 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: Russian \n" "Language: ru\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%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n" #, python-brace-format msgid "once" msgid_plural "{N} times" msgstr[0] "paз" msgstr[1] "{N} paзи" msgstr[2] "{N} paзiв" i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-msgid-error.po0000644000000000000000000000103413733665553027762 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" #, python-brace-format msgid "A quick brown fox jumps over the lazy dog}" msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis}" i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-msgid-error.pot0000644000000000000000000000117413733665553030153 0ustar00rootroot00000000000000# E: python-brace-format-string-error msgid 'A quick brown fox jumps over the lazy dog}': invalid replacement field specification '}' #, 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" #, python-brace-format msgid "A quick brown fox jumps over the lazy dog}" msgstr "" i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-no-excess-arguments.po0000644000000000000000000000122113733665553031435 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: Russian \n" "Language: ru\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%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n" #, python-brace-format msgid "once" msgid_plural "{N} times" msgstr[0] "{N} paз" msgstr[1] "{N} paзи" msgstr[2] "{N} paзiв" i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-okay.po0000644000000000000000000000103213733665553026471 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" #, python-brace-format msgid "A quick brown {} jumps over the lazy dog." msgstr "Sic fugiens, {}, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-okay.pot0000644000000000000000000000076413733665553026670 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" #, python-brace-format msgid "A quick brown {} jumps over the lazy dog." msgstr "" i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-omitted-numeral-1.po0000644000000000000000000000150113733665553030773 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" #, python-brace-format msgid "{N} quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi." msgstr[2] "Mężny bądź, chroń pułk twój i {N} flag." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-omitted-numeral-2.po0000644000000000000000000000147713733665553031010 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" #, python-brace-format msgid "A quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi." msgstr[2] "Mężny bądź, chroń pułk twój i {N} flag." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-omitted-numeral-5.po0000644000000000000000000000305013733665553031000 0ustar00rootroot00000000000000# E: python-brace-format-string-missing-argument msgid 'A quick brown fox jumps over the lazy dog.' msgctxt 'max 6': N not in msgstr[2] while in msgid_plural 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" # {N} doesn't have to be included in msgstr[2], because according to the range # flag, it applies only to n=5. #, python-brace-format, range: 1..5 msgctxt "max 5" msgid "A quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi." msgstr[2] "Mężny bądź, chroń pułk twój i pięć flag." # {N} cannot be omitted in msgstr[2], because it applies not only to n=5 but # also n=6. #, python-brace-format, range: 1..6 msgctxt "max 6" msgid "A quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi." msgstr[2] "Mężny bądź, chroń pułk twój i pięć flag." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-omitted-numeral.pot0000644000000000000000000000117113733665553031024 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, python-brace-format msgid "A quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-plural-okay.po0000644000000000000000000000147513733665553030001 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" #, python-brace-format msgid "{N} quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i {N} flagę." msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi." msgstr[2] "Mężny bądź, chroń pułk twój i {N} flag." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-plural-okay.pot0000644000000000000000000000117313733665553030160 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, python-brace-format msgid "{N} quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-precision-range-error.po0000644000000000000000000000125613733665553031752 0ustar00rootroot00000000000000# E: python-brace-format-string-error msgid 'A quick brown {} jumps over the lazy dog.': invalid format specification '{:.9999999999}' 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" #, python-brace-format msgid "A quick brown {} jumps over the lazy dog." msgstr "Sic fugiens, {:.9999999999}, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-unknown-argument-1.po0000644000000000000000000000123513733665553031210 0ustar00rootroot00000000000000# E: python-brace-format-string-unknown-argument msgid 'A quick brown {A} jumps over the lazy dog.': B in msgstr but not in msgid 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" #, python-brace-format msgid "A quick brown {A} jumps over the lazy dog." msgstr "Sic fugiens, {A}, zelotypos, quam {B} haberis." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-unknown-argument-2.po0000644000000000000000000000211713733665553031211 0ustar00rootroot00000000000000# E: python-brace-format-string-unknown-argument msgid '{N} quick brown fox jumps over the lazy dog.': O in msgstr[0] but not in msgid # E: python-brace-format-string-unknown-argument msgid '{N} quick brown fox jumps over the lazy dog.': O in msgstr[2] but not in msgid_plural 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" #, python-brace-format msgid "{N} quick brown fox jumps over the lazy dog." msgid_plural "{N} quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń {O} twój i {N} flagę." msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi." msgstr[2] "Mężny bądź, chroń {O} twój i {N} flag." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-unknown-argument.pot0000644000000000000000000000140213733665553031232 0ustar00rootroot00000000000000# E: python-brace-format-string-unknown-argument msgid '{N} quick brown fox jumps over the lazy dog.': N in msgid but not in msgid_plural #, 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, python-brace-format msgid "{N} quick brown fox jumps over the lazy dog." msgid_plural "Quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-valid-conversion-flag.po0000644000000000000000000000103413733665553031721 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" #, python-brace-format msgid "A quick brown {} jumps over the lazy dog." msgstr "Sic fugiens, {!s}, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-width-range-error.po0000644000000000000000000000125413733665553031074 0ustar00rootroot00000000000000# E: python-brace-format-string-error msgid 'A quick brown {} jumps over the lazy dog.': invalid format specification '{:9999999999}' 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" #, python-brace-format msgid "A quick brown {} jumps over the lazy dog." msgstr "Sic fugiens, {:9999999999}, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-format-string-argument-mixture.po0000644000000000000000000000123613733665553027777 0ustar00rootroot00000000000000# E: python-format-string-error msgid 'A quick brown %s jumps over the lazy %s.': mixed named and unnamed argument specifications '%(n)d' 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" #, python-format msgid "A quick brown %s jumps over the lazy %s." msgstr "Sic fugiens, %s, zelotypos, quam %(n)d haberis." i18nspector-0.26/tests/blackbox_tests/python-format-string-argument-number-mismatch-1.po0000644000000000000000000000161113733665553031530 0ustar00rootroot00000000000000# E: python-format-string-argument-number-mismatch msgid 'A quick brown %s jumps over the lazy dog.': 2 (msgstr) != 1 (msgid) # E: python-format-string-argument-number-mismatch msgid 'A quick brown %s jumps over the lazy %s.': 1 (msgstr) != 2 (msgid) 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" #, python-format msgid "A quick brown %s jumps over the lazy dog." msgstr "Sic fugiens, %s, zelotypos, quam %s haberis." #, python-format msgid "A quick brown %s jumps over the lazy %s." msgstr "Sic fugiens, %s, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-format-string-argument-number-mismatch-2.po0000644000000000000000000000210513733665553031530 0ustar00rootroot00000000000000# E: python-format-string-argument-number-mismatch msgid '%d quick brown fox jumps over the lazy dog.': 0 (msgstr[0]) != 1 (msgid) # E: python-format-string-argument-number-mismatch msgid '%d quick brown fox jumps over the lazy dog.': 2 (msgstr[2]) != 1 (msgid_plural) 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" #, python-format 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 jedną 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.26/tests/blackbox_tests/python-format-string-argument-number-mismatch.pot0000644000000000000000000000234213733665553031560 0ustar00rootroot00000000000000# I: python-format-string-unnamed-plural-argument msgid '%d quick brown fox jumps over the lazy dog.' # E: python-format-string-argument-number-mismatch msgid '%d quick brown fox jumps over the lazy dog.': 1 (msgid) != 0 (msgid_plural) # I: python-format-string-unnamed-plural-argument msgid 'A quick brown fox jumps over the lazy dog.' # E: python-format-string-argument-number-mismatch msgid 'A quick brown fox jumps over the lazy dog.': 0 (msgid) != 1 (msgid_plural) #, 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, python-format msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "Quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" #, python-format msgid "A 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.26/tests/blackbox_tests/python-format-string-argument-type-mismatch-1.po0000644000000000000000000000163313733665553031225 0ustar00rootroot00000000000000# E: python-format-string-argument-type-mismatch msgid 'A quick brown %s jumps over the lazy dog.': int (msgstr) != str (msgid) # E: python-format-string-argument-type-mismatch msgid 'A quick brown %(O)s jumps over the lazy dog.': int (msgstr) != str (msgid) 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" #, python-format msgid "A quick brown %s jumps over the lazy dog." msgstr "Sic fugiens, %d, zelotypos, quam Karus haberis." #, python-format msgid "A quick brown %(O)s jumps over the lazy dog." msgstr "Sic fugiens, %(O)d, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-format-string-argument-type-mismatch-2.po0000644000000000000000000000324313733665553031225 0ustar00rootroot00000000000000# E: python-format-string-argument-type-mismatch msgid '%d quick brown fox jumps over the lazy dog.': str (msgstr[0]) != int (msgid) # E: python-format-string-argument-type-mismatch msgid '%d quick brown fox jumps over the lazy dog.': object (msgstr[2]) != int (msgid_plural) # E: python-format-string-argument-type-mismatch msgid '%(N)d quick brown fox jumps over the lazy dog.': str (msgstr[0]) != int (msgid) # E: python-format-string-argument-type-mismatch msgid '%(N)d quick brown fox jumps over the lazy dog.': object (msgstr[2]) != int (msgid_plural) 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" #, python-format 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 %s 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 %r flag." #, python-format msgid "%(N)d quick brown fox jumps over the lazy dog." msgid_plural "%(N)d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %(N)s flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %(N)d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %(N)r flag." i18nspector-0.26/tests/blackbox_tests/python-format-string-argument-type-mismatch.pot0000644000000000000000000000221713733665553031252 0ustar00rootroot00000000000000# I: python-format-string-unnamed-plural-argument msgid '%d quick brown fox jumps over the lazy dog.' # E: python-format-string-argument-type-mismatch msgid '%d quick brown fox jumps over the lazy dog.': int (msgid) != str (msgid_plural) # E: python-format-string-argument-type-mismatch msgid '%(N)d quick brown fox jumps over the lazy dog.': int (msgid) != str (msgid_plural) #, 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, python-format msgid "%d quick brown fox jumps over the lazy dog." msgid_plural "%s quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" #, python-format msgid "%(N)d quick brown fox jumps over the lazy dog." msgid_plural "%(N)s quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/python-format-string-duplicate-flag.po0000644000000000000000000000121513733665553027340 0ustar00rootroot00000000000000# P: python-format-string-redundant-flag msgid 'A quick brown %--s jumps over the lazy dog.': duplicate - in '%--s' 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" #, python-format msgid "A quick brown %--s jumps over the lazy dog." msgstr "Sic fugiens, %--s, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-format-string-error-argument-type-mismatch.po0000644000000000000000000000122713733665553032215 0ustar00rootroot00000000000000# E: python-format-string-error msgid 'A quick brown %(O)s jumps over the lazy %(O)s.': argument type mismatch O int, str 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" #, python-format msgid "A quick brown %(O)s jumps over the lazy %(O)s." msgstr "Sic fugiens, %(O)s, zelotypos, quam %(O)d haberis." i18nspector-0.26/tests/blackbox_tests/python-format-string-error.po0000644000000000000000000000122013733665553025604 0ustar00rootroot00000000000000# E: python-format-string-error msgid 'A quick brown fox jumps over the lazy dog.': invalid conversion specification '%' 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" #, python-format msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis%" i18nspector-0.26/tests/blackbox_tests/python-format-string-forbidden-argument-key.po0000644000000000000000000000124413733665553031023 0ustar00rootroot00000000000000# E: python-format-string-error msgid '100%% of quick brown foxes jump over the lazy %(O)s.': argument key not allowed '%(P)%' 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" #, python-format msgid "100%% of quick brown foxes jump over the lazy %(O)s." msgstr "Mężny bądź, chroń %(O)s twój i 100%(P)% flag." i18nspector-0.26/tests/blackbox_tests/python-format-string-missing-argument.po0000644000000000000000000000123513733665553027752 0ustar00rootroot00000000000000# E: python-format-string-missing-argument msgid 'A quick brown %(A)s jumps over the lazy %(B)s.': A not in msgstr while in msgid 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" #, python-format msgid "A quick brown %(A)s jumps over the lazy %(B)s." msgstr "Sic fugiens, dux, zelotypos, quam %(B)s haberis." i18nspector-0.26/tests/blackbox_tests/python-format-string-missing-non-numeral.po0000644000000000000000000000171113733665553030362 0ustar00rootroot00000000000000# E: python-format-string-missing-argument msgid '%(N)s quick brown fox jumps over the lazy dog.': N not in msgstr[0] while in msgid 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" #, python-format msgid "%(N)s quick brown fox jumps over the lazy dog." msgid_plural "%(N)s quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %(N)s flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %(N)s flag." i18nspector-0.26/tests/blackbox_tests/python-format-string-missing-non-numeral.pot0000644000000000000000000000137213733665553030551 0ustar00rootroot00000000000000# E: python-format-string-missing-argument msgid 'A quick brown fox jumps over the lazy dog.': N not in msgid while in msgid_plural #, 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, python-format msgid "A quick brown fox jumps over the lazy dog." msgid_plural "%(N)s quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/python-format-string-missing-numeral.po0000644000000000000000000000135613733665553027577 0ustar00rootroot00000000000000# E: python-format-string-missing-argument msgid once: N not in msgstr[0] while in msgid_plural 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: Russian \n" "Language: ru\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%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n" #, python-format msgid "once" msgid_plural "%(N)d times" msgstr[0] "paз" msgstr[1] "%(N)d paзи" msgstr[2] "%(N)d paзiв" i18nspector-0.26/tests/blackbox_tests/python-format-string-msgid-error.po0000644000000000000000000000102613733665553026711 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" #, python-format msgid "A quick brown fox jumps over the lazy dog%" msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis%" i18nspector-0.26/tests/blackbox_tests/python-format-string-msgid-error.pot0000644000000000000000000000115113733665553027074 0ustar00rootroot00000000000000# E: python-format-string-error msgid 'A quick brown fox jumps over the lazy dog%': invalid conversion specification '%' #, 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" #, python-format msgid "A quick brown fox jumps over the lazy dog%" msgstr "" i18nspector-0.26/tests/blackbox_tests/python-format-string-multiple-unnamed-arguments.pot0000644000000000000000000000112413733665553032125 0ustar00rootroot00000000000000# E: python-format-string-multiple-unnamed-arguments msgid 'A quick brown %s jumps over the lazy %s.' #, 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" #, python-format msgid "A quick brown %s jumps over the lazy %s." msgstr "" i18nspector-0.26/tests/blackbox_tests/python-format-string-no-excess-arguments.po0000644000000000000000000000120713733665553030367 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: Russian \n" "Language: ru\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%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n" #, python-format msgid "once" msgid_plural "%d times" msgstr[0] "%d paз" msgstr[1] "%d paзи" msgstr[2] "%d paзiв" i18nspector-0.26/tests/blackbox_tests/python-format-string-obsolete-conversion.po0000644000000000000000000000121013733665553030451 0ustar00rootroot00000000000000# P: python-format-string-obsolete-conversion msgid '%d quick brown foxes jump over the lazy dog.': '%u' => '%d' 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" #, python-format msgid "%d quick brown foxes jump over the lazy dog." msgstr "Mężny bądź, chroń pułk twój i %u flag." i18nspector-0.26/tests/blackbox_tests/python-format-string-obsolete-conversion.pot0000644000000000000000000000114313733665553030642 0ustar00rootroot00000000000000# P: python-format-string-obsolete-conversion msgid '%u quick brown foxes jump over the lazy dog.': '%u' => '%d' #, 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" #, python-format msgid "%u quick brown foxes jump over the lazy dog." msgstr "" i18nspector-0.26/tests/blackbox_tests/python-format-string-okay.po0000644000000000000000000000102413733665553025420 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" #, python-format msgid "A quick brown %s jumps over the lazy dog." msgstr "Sic fugiens, %s, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-format-string-okay.pot0000644000000000000000000000075613733665553025617 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" #, python-format msgid "A quick brown %s jumps over the lazy dog." msgstr "" i18nspector-0.26/tests/blackbox_tests/python-format-string-omitted-numeral-1.po0000644000000000000000000000150313733665553027723 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" #, python-format msgid "%(N)d quick brown fox jumps over the lazy dog." msgid_plural "%(N)d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %(N)d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %(N)d flag." i18nspector-0.26/tests/blackbox_tests/python-format-string-omitted-numeral-2.po0000644000000000000000000000147713733665553027736 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" #, python-format msgid "A quick brown fox jumps over the lazy dog." msgid_plural "%(N)d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %(N)d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %(N)d flag." i18nspector-0.26/tests/blackbox_tests/python-format-string-omitted-numeral-5.po0000644000000000000000000000304213733665553027727 0ustar00rootroot00000000000000# E: python-format-string-missing-argument msgid 'A quick brown fox jumps over the lazy dog.' msgctxt 'max 6': N not in msgstr[2] while in msgid_plural 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" # %(N)d doesn't have to be included in msgstr[2], because according to the range # flag, it applies only to n=5. #, python-format, range: 1..5 msgctxt "max 5" msgid "A quick brown fox jumps over the lazy dog." msgid_plural "%(N)d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %(N)d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i pięć flag." # %(N)d cannot be omitted in msgstr[2], because it applies not only to n=5 but # also n=6. #, python-format, range: 1..6 msgctxt "max 6" msgid "A quick brown fox jumps over the lazy dog." msgid_plural "%(N)d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %(N)d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i pięć flag." i18nspector-0.26/tests/blackbox_tests/python-format-string-omitted-numeral.pot0000644000000000000000000000116513733665553027755 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, python-format msgid "A quick brown fox jumps over the lazy dog." msgid_plural "%(N)d quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/python-format-string-overridden-flag-1.po0000644000000000000000000000124413733665553027667 0ustar00rootroot00000000000000# P: python-format-string-redundant-flag msgid '%d%% of quick brown foxes jump over the lazy dog.': '+' overridden by ' ' in '%+ d' 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" #, python-format msgid "%d%% of quick brown foxes jump over the lazy dog." msgstr "Mężny bądź, chroń pułk twój i %+ d%% flag." i18nspector-0.26/tests/blackbox_tests/python-format-string-overridden-flag-2.po0000644000000000000000000000122213733665553027664 0ustar00rootroot00000000000000# P: python-format-string-redundant-flag msgid '%d%% of quick brown foxes jump over the lazy dog.': 0 in '%0.3d' 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" #, python-format msgid "%d%% of quick brown foxes jump over the lazy dog." msgstr "Mężny bądź, chroń pułk twój i %0.3d%% flag." i18nspector-0.26/tests/blackbox_tests/python-format-string-plural-okay.po0000644000000000000000000000150113733665553026715 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" #, python-format msgid "%(N)d quick brown fox jumps over the lazy dog." msgid_plural "%(N)d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %(N)d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %(N)d flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %(N)d flag." i18nspector-0.26/tests/blackbox_tests/python-format-string-plural-okay.pot0000644000000000000000000000117113733665553027104 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, python-format msgid "%(N)d quick brown fox jumps over the lazy dog." msgid_plural "%(N)d quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/python-format-string-precision-range-error.po0000644000000000000000000000122713733665553030676 0ustar00rootroot00000000000000# E: python-format-string-error msgid 'A quick brown %s jumps over the lazy dog.': precision too large '%.9999999999s' 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" #, python-format msgid "A quick brown %s jumps over the lazy dog." msgstr "Sic fugiens, %.9999999999s, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-format-string-redundant-flag.po0000644000000000000000000000117713733665553027361 0ustar00rootroot00000000000000# P: python-format-string-redundant-flag msgid 'A quick brown %s jumps over the lazy dog.': '#' in '%#s' 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" #, python-format msgid "A quick brown %s jumps over the lazy dog." msgstr "Sic fugiens, %#s, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-format-string-redundant-flag.pot0000644000000000000000000000113013733665553027532 0ustar00rootroot00000000000000# P: python-format-string-redundant-flag msgid 'A quick brown %0s jumps over the lazy dog.': 0 in '%0s' #, 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" #, python-format msgid "A quick brown %0s jumps over the lazy dog." msgstr "" i18nspector-0.26/tests/blackbox_tests/python-format-string-redundant-length.po0000644000000000000000000000117713733665553027731 0ustar00rootroot00000000000000# P: python-format-string-redundant-length msgid 'A quick brown %s jumps over the lazy dog.': h in '%hs' 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" #, python-format msgid "A quick brown %s jumps over the lazy dog." msgstr "Sic fugiens, %hs, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/python-format-string-redundant-length.pot0000644000000000000000000000113213733665553030104 0ustar00rootroot00000000000000# P: python-format-string-redundant-length msgid 'A quick brown %ls jumps over the lazy dog.': l in '%ls' #, 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" #, python-format msgid "A quick brown %ls jumps over the lazy dog." msgstr "" i18nspector-0.26/tests/blackbox_tests/python-format-string-redundant-precision.po0000644000000000000000000000122313733665553030433 0ustar00rootroot00000000000000# P: python-format-string-redundant-precision msgid 'A quick brown fox jumps over the lazy dog%.42c': 42 in '%.42c' 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" #, python-format msgid "A quick brown fox jumps over the lazy dog%.42c" msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis%.42c" i18nspector-0.26/tests/blackbox_tests/python-format-string-redundant-precision.pot0000644000000000000000000000115013733665553030616 0ustar00rootroot00000000000000# P: python-format-string-redundant-precision msgid 'A quick brown fox jumps over the lazy dog%.42c': 42 in '%.42c' #, 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" #, python-format msgid "A quick brown fox jumps over the lazy dog%.42c" msgstr "" i18nspector-0.26/tests/blackbox_tests/python-format-string-unknown-argument-1.po0000644000000000000000000000123113733665553030132 0ustar00rootroot00000000000000# E: python-format-string-unknown-argument msgid 'A quick brown %(A)s jumps over the lazy dog.': B in msgstr but not in msgid 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" #, python-format msgid "A quick brown %(A)s jumps over the lazy dog." msgstr "Sic fugiens, %(A)s, zelotypos, quam %(B)s haberis." i18nspector-0.26/tests/blackbox_tests/python-format-string-unknown-argument-2.po0000644000000000000000000000211713733665553030137 0ustar00rootroot00000000000000# E: python-format-string-unknown-argument msgid '%(N)d quick brown fox jumps over the lazy dog.': O in msgstr[0] but not in msgid # E: python-format-string-unknown-argument msgid '%(N)d quick brown fox jumps over the lazy dog.': O in msgstr[2] but not in msgid_plural 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" #, python-format msgid "%(N)d quick brown fox jumps over the lazy dog." msgid_plural "%(N)d quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń %(O)s twój i %(N)d flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %(N)d flagi." msgstr[2] "Mężny bądź, chroń %(O)s twój i %(N)d flag." i18nspector-0.26/tests/blackbox_tests/python-format-string-unknown-argument.pot0000644000000000000000000000137213733665553030166 0ustar00rootroot00000000000000# E: python-format-string-unknown-argument msgid '%(N)d quick brown fox jumps over the lazy dog.': N in msgid but not in msgid_plural #, 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" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #, python-format msgid "%(N)d quick brown fox jumps over the lazy dog." msgid_plural "Quick brown foxes jump over the lazy dog." msgstr[0] "" msgstr[1] "" i18nspector-0.26/tests/blackbox_tests/python-format-string-width-range-error.po0000644000000000000000000000122713733665553030022 0ustar00rootroot00000000000000# E: python-format-string-error msgid 'A quick brown %s jumps over the lazy dog.': field width too large '%9999999999s' 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" #, python-format msgid "A quick brown %s jumps over the lazy dog." msgstr "Sic fugiens, %9999999999s, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/qt-plural-format-mistaken-for-c-format.po0000644000000000000000000000161613733665553027665 0ustar00rootroot00000000000000# E: qt-plural-format-mistaken-for-c-format msgid '%n 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" #, c-format msgid "%n quick brown fox jumps over the lazy dog." msgid_plural "%n quick brown foxes jump over the lazy dog." msgstr[0] "Mężny bądź, chroń pułk twój i %n flagę." msgstr[1] "Mężny bądź, chroń pułk twój i %n flagi." msgstr[2] "Mężny bądź, chroń pułk twój i %n flag." i18nspector-0.26/tests/blackbox_tests/range-flag-without-plural-string.po0000644000000000000000000000107313733665553026655 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.26/tests/blackbox_tests/redundant-message-flag.po0000644000000000000000000000123513733665553024665 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.26/tests/blackbox_tests/rfc2606-in-language-team.po0000644000000000000000000000107713733665553024555 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.26/tests/blackbox_tests/rfc2606-in-last-translator.po0000644000000000000000000000110613733665553025171 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.26/tests/blackbox_tests/rfc2606-in-report-msgid-bugs-to.po0000644000000000000000000000110613733665553026031 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.26/tests/blackbox_tests/seemingly-duplicate-message-definition.po0000644000000000000000000000120313733665553030057 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.26/tests/blackbox_tests/stray-header-line-1.po0000644000000000000000000000114313733665553024021 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.26/tests/blackbox_tests/stray-header-line-2.po0000644000000000000000000000116213733665553024023 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.26/tests/blackbox_tests/stray-header-line-3.po0000644000000000000000000000115413733665553024025 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.26/tests/blackbox_tests/stray-previous-msgid.po0000644000000000000000000000121313733665553024461 0ustar00rootroot00000000000000# W: stray-previous-msgid 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 "The quick brown fox jumps over the lazy dog." msgid "A quick brown fox jumps over the lazy dog." msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis." i18nspector-0.26/tests/blackbox_tests/syntax-error-in-plural-expression.po0000644000000000000000000000176313733665553027131 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.26/tests/blackbox_tests/syntax-error-in-unused-plural-expression.po0000644000000000000000000000151013733665553030420 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.26/tests/blackbox_tests/syntax-error.po0000644000000000000000000000077013733665553023030 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.26/tests/blackbox_tests/trailing-comment.po0000644000000000000000000000101513733665553023615 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.26/tests/blackbox_tests/trailing-junk-in-plural-forms.po0000644000000000000000000000151013733665553026147 0ustar00rootroot00000000000000# E: trailing-junk-in-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" 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.26/tests/blackbox_tests/translation-in-template.pot0000644000000000000000000000113713733665553025310 0ustar00rootroot00000000000000# W: translation-in-template msgid 'A quick brown fox jumps over the lazy dog.' #, 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.26/tests/blackbox_tests/typoed-flag-for-header-entry.po0000644000000000000000000000110413733665553025727 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.26/tests/blackbox_tests/typoed-header-field-name.po0000644000000000000000000000116113733665553025077 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.26/tests/blackbox_tests/unexpected-flag-for-header-entry.po0000644000000000000000000000107513733665553026576 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.26/tests/blackbox_tests/unknown-encoding.po0000644000000000000000000000104413733665553023631 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.26/tests/blackbox_tests/unknown-file-type.pop0000644000000000000000000000105213733665553024120 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.26/tests/blackbox_tests/unknown-format-flag.po0000644000000000000000000000116713733665553024250 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.26/tests/blackbox_tests/unknown-header-field-no-duplicate-hint.po0000644000000000000000000000126313733665553027701 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.26/tests/blackbox_tests/unknown-header-field.po0000644000000000000000000000111213733665553024350 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.26/tests/blackbox_tests/unknown-message-flag.po0000644000000000000000000000114313733665553024376 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.26/tests/blackbox_tests/unknown-poedit-language.po0000644000000000000000000000110413733665553025105 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.26/tests/blackbox_tests/unknown-x-header-field-1.po0000644000000000000000000000104713733665553024762 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" "X-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.26/tests/blackbox_tests/unknown-x-header-field-2.po0000644000000000000000000000104713733665553024763 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" "x-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.26/tests/blackbox_tests/unrepresentable-characters-euro.po0000644000000000000000000000135713733665553026640 0ustar00rootroot00000000000000# I: language-variant-does-not-affect-translation 'pl@euro' # E: unrepresentable-characters ISO-8859-1 <...> # E: unusual-character-in-translation msgid 'A quick brown fox jumps over the lazy dog.': 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.26/tests/blackbox_tests/unrepresentable-characters.po0000644000000000000000000000125613733665553025666 0ustar00rootroot00000000000000# E: unrepresentable-characters ISO-8859-1 <...> # E: unusual-character-in-translation msgid 'A quick brown fox jumps over the lazy dog.': 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.26/tests/blackbox_tests/unusual-character-in-plural-translation.po0000644000000000000000000000162413733665553030235 0ustar00rootroot00000000000000# E: unusual-character-in-translation msgid '%d quick brown fox jumps over the lazy dog.': U+FFFF non-character 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.26/tests/blackbox_tests/unusual-number-of-plural-forms.po0000644000000000000000000000151213733665553026353 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.26/tests/blackbox_tests/unusual-unused-plural-forms.po0000644000000000000000000000131613733665553025766 0ustar00rootroot00000000000000# W: unusual-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.26/tests/blackbox_tests/valid-range-flag.po0000644000000000000000000000146013733665553023450 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.26/tests/blackbox_tests/xfail-header-imitation.po0000644000000000000000000000153413733665553024676 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 # This msgid should sort first asciibetically, # so that the entry ends up first in the MO file, too. 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.26/tests/blackbox_tests/xfail-partially-translated-message-2.po0000644000000000000000000000157013733665553027374 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" # msgstr[2] doesn't have to be translated, because (according to the range # flag) it will never be used. #, c-format, range: 1..4 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] "" i18nspector-0.26/tests/blackbox_tests/zero-bytes-file.mo0000644000000000000000000000000013733665553023352 0ustar00rootroot00000000000000i18nspector-0.26/tests/blackbox_tests/zero-bytes-file.mo.tags0000644000000000000000000000004413733665553024317 0ustar00rootroot00000000000000E: invalid-mo-file unexpected magic i18nspector-0.26/tests/blackbox_tests/zero-bytes-file.po0000644000000000000000000000000013733665553023355 0ustar00rootroot00000000000000i18nspector-0.26/tests/blackbox_tests/zero-bytes-file.po.tags0000644000000000000000000000077313733665553024333 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 W: empty-file i18nspector-0.26/tests/blackbox_tests/zero-division-error-in-plural-forms.po0000644000000000000000000000153613733665553027331 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.26/tests/blackbox_tests/zero-division-error-in-unused-plural-forms.po0000644000000000000000000000126013733665553030624 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.26/tests/coverage0000644000000000000000000000642113733665553016521 0ustar00rootroot00000000000000Generated automatically by private/update-branch-coverage. Do not edit. Name Stmts Miss Branch BrPart Cover Missing ------------------------------------------------------------------------------ lib/__init__.py 1 0 0 0 100% lib/check/__init__.py 810 749 515 0 5% 83-87, 90-103, 118-203, 206-222, 226-358, 362-506, 510-582, 586-629, 634-669, 674-718, 721-799, 802-882, 885-999, 1002-1009, 1012-1028, 1033 lib/check/msgformat/__init__.py 83 68 36 0 13% 31, 38, 41-151 lib/check/msgformat/c.py 67 56 36 0 11% 37-44, 47-105, 108-129 lib/check/msgformat/perlbrace.py 28 19 6 0 26% 37-48, 51-65 lib/check/msgformat/pybrace.py 35 26 13 0 19% 37-48, 51-75 lib/check/msgformat/python.py 77 67 47 0 8% 37-109, 112-149 lib/check/msgrepr.py 11 7 2 0 31% 28-34 lib/cli.py 161 125 46 0 17% 45-49, 58-67, 70-71, 74-76, 82-111, 114-119, 125-131, 134-142, 145-153, 159, 168-186, 189-195, 198-232 lib/domains.py 15 0 0 0 100% lib/encodings.py 134 40 36 2 72% 50-66, 78-86, 134->138, 138-142, 193->195, 195, 209-222, 226-230 lib/gettext.py 105 0 36 0 100% lib/iconv.py 156 49 58 19 64% 41-42, 55-57, 63->64, 64, 65->66, 66, 67->68, 68, 69->70, 70, 82->83, 83-84, 96->97, 97-98, 105->110, 110->111, 111-123, 129->130, 129->exit, 130-131, 134-145, 150->151, 151, 152->153, 153, 154->155, 155, 156->157, 157, 165->166, 166-167, 179->180, 180-181, 198->213, 200->203, 203-204, 213, 221->222, 222-223, 226-237 lib/intexpr.py 420 0 126 0 100% lib/ling.py 243 2 98 3 99% 159->162, 179->181, 181, 277->283, 281 lib/misc.py 42 0 16 0 100% lib/moparser.py 138 92 56 3 28% 56->58, 68, 74->76, 76, 91-109, 112-178, 183-192, 194->195, 195 lib/paths.py 7 2 0 0 71% 36-37 lib/polib4us.py 120 75 26 0 31% 41-42, 56, 72, 75-96, 100, 110-112, 133-145, 149, 161, 170-175, 186-194, 205, 208, 212-216, 228-235, 243-252 lib/strformat/__init__.py 0 0 0 0 100% lib/strformat/c.py 285 0 168 0 100% lib/strformat/perlbrace.py 27 0 8 0 100% lib/strformat/pybrace.py 156 0 74 0 100% lib/strformat/python.py 204 0 94 0 100% lib/tags.py 117 29 34 4 75% 81->82, 82, 83->84, 84, 86->87, 87, 106-107, 118-120, 125-127, 139->140, 140, 151-158, 164-168, 178-191, 210, 216 lib/terminal.py 48 17 6 1 59% 37-38, 63->64, 64, 80-93 lib/xml.py 21 0 2 0 100% ------------------------------------------------------------------------------ TOTAL 3511 1423 1539 32 55% i18nspector-0.26/tests/fuzzing/0000755000000000000000000000000013733665553016474 5ustar00rootroot00000000000000i18nspector-0.26/tests/fuzzing/mo-parser/0000755000000000000000000000000013733665553020401 5ustar00rootroot00000000000000i18nspector-0.26/tests/fuzzing/mo-parser/run0000755000000000000000000000271013733665553021133 0ustar00rootroot00000000000000#!/bin/sh # Copyright © 2015-2018 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. set -e here=$(dirname "$0") output="$here/output" if [ -e "$output/" ] then input=- else input=$(mktemp -d -t i18nspector.fuzzing.XXXXXX) cp "$here/../../blackbox_tests/"*.mo "$input/" fi export AFL_FAST_CAL=1 exec py-afl-fuzz -m 100 -i "$input" -o "$output" -T i18nspector-mo-parser -- python3 "$here/test.py" # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/fuzzing/mo-parser/test.py0000644000000000000000000000403013733665553021727 0ustar00rootroot00000000000000# Copyright © 2015-2018 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 encodings import importlib import os import pkgutil import sys import afl sys.path[0] += '/../../..' import tests.tools import lib.moparser as M temporary_file = tests.tools.temporary_file def parser_for_bytes(data): with temporary_file(suffix='.mo') as file: file.write(data) file.flush() return M.Parser(file.name) def test(data): try: parser_for_bytes(data) except M.SyntaxError: return except UnicodeDecodeError: pass def main(): for _, modname, _ in pkgutil.iter_modules(encodings.__path__, prefix='encodings.'): try: importlib.import_module(modname) except (LookupError, ImportError): pass while afl.loop(max=1000): data = sys.stdin.buffer.read() # pylint: disable=no-member test(data) os._exit(0) # pylint: disable=protected-access if __name__ == '__main__': main() # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/fuzzing/plural-forms/0000755000000000000000000000000013733665553021117 5ustar00rootroot00000000000000i18nspector-0.26/tests/fuzzing/plural-forms/input/0000755000000000000000000000000013733665553022256 5ustar00rootroot00000000000000i18nspector-0.26/tests/fuzzing/plural-forms/input/p10000644000000000000000000000002613733665553022517 0ustar00rootroot00000000000000nplurals=1; plural=0; i18nspector-0.26/tests/fuzzing/plural-forms/input/p2b0000644000000000000000000000003213733665553022657 0ustar00rootroot00000000000000nplurals=2; plural=n > 1; i18nspector-0.26/tests/fuzzing/plural-forms/input/p3a0000644000000000000000000000007013733665553022661 0ustar00rootroot00000000000000nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2; i18nspector-0.26/tests/fuzzing/plural-forms/input/p3b0000644000000000000000000000007613733665553022670 0ustar00rootroot00000000000000nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2; i18nspector-0.26/tests/fuzzing/plural-forms/input/p3c0000644000000000000000000000013213733665553022662 0ustar00rootroot00000000000000nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2; i18nspector-0.26/tests/fuzzing/plural-forms/input/p3d0000644000000000000000000000014513733665553022667 0ustar00rootroot00000000000000nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; i18nspector-0.26/tests/fuzzing/plural-forms/input/p3e0000644000000000000000000000011313733665553022663 0ustar00rootroot00000000000000nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2; i18nspector-0.26/tests/fuzzing/plural-forms/input/p3f0000644000000000000000000000012513733665553022667 0ustar00rootroot00000000000000nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; i18nspector-0.26/tests/fuzzing/plural-forms/input/p3g0000644000000000000000000000005413733665553022671 0ustar00rootroot00000000000000nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2; i18nspector-0.26/tests/fuzzing/plural-forms/input/p4a0000644000000000000000000000011713733665553022664 0ustar00rootroot00000000000000nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3; i18nspector-0.26/tests/fuzzing/plural-forms/input/p4b0000644000000000000000000000016013733665553022663 0ustar00rootroot00000000000000nplurals=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; i18nspector-0.26/tests/fuzzing/plural-forms/run0000755000000000000000000000250513733665553021653 0ustar00rootroot00000000000000#!/bin/sh # Copyright © 2015-2018 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. set -e here=$(dirname "$0") input="$here/input" output="$here/output" [ -e "$output/" ] && input=- export AFL_FAST_CAL=1 exec py-afl-fuzz -i "$input" -o "$output" -T i18nspector-plural-forms -- python3 "$here/test.py" i18nspector-0.26/tests/fuzzing/plural-forms/test.py0000644000000000000000000000337013733665553022453 0ustar00rootroot00000000000000# Copyright © 2015 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 afl sys.path[0] += '/../../..' from lib import gettext def test(s): try: (n, expr) = gettext.parse_plural_forms(s) except gettext.PluralFormsSyntaxError: return del n for i in range(200): try: expr(i) except OverflowError: return except ZeroDivisionError: return def main(): while afl.loop(max=1000): s = sys.stdin.buffer.read() # pylint: disable=no-member s = s.decode('UTF-8', 'replace') test(s) os._exit(0) # pylint: disable=protected-access if __name__ == '__main__': main() # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/run-tests0000755000000000000000000000271313733665553016675 0ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright © 2013-2016 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 tempfile import nose sys.path[0] += '/..' from tests import blackbox_tests if __name__ == '__main__': with tempfile.TemporaryDirectory(prefix='i18nspector.tests.') as tmpdir: os.environ['XDG_CACHE_HOME'] = tmpdir nose.main(addplugins=[blackbox_tests.Plugin()]) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/test_changelog.py0000644000000000000000000000767313733665553020355 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. import os import re from nose.tools import ( assert_not_equal, ) import lib.tags here = os.path.dirname(__file__) docdir = os.path.join(here, os.pardir, 'doc') summary_re = re.compile( '^ [*] Summary of tag changes:((?:\n .*)+\n)', re.MULTILINE ) summary_details_re = re.compile( r'\A\n' r'(?:' r' [+] Added:\n' r'(?P(?:' r' - [\w-]+\n' r')+))?' r'(?:' r' [+] Renamed:\n' r'(?P(?:' r' - [\w-]+ [(]from [\w-]+[)]\n' r')+))?' r'\Z' ) rename_re = re.compile( r'([\w-]+) [(]from ([\w-]+)[)]' ) def test_tags(): path = os.path.join(docdir, 'changelog') with open(path, 'rt', encoding='UTF-8') as file: changelog = file.read() summaries = summary_re.findall(changelog) changelog_tags = set() def add(info, tag): del info if tag in changelog_tags: raise AssertionError('changelog adds tag twice: ' + tag) changelog_tags.add(tag) def remove(info, tag): del info if tag not in changelog_tags: raise AssertionError('changelog removes non-existent tag: ' + tag) changelog_tags.remove(tag) def rename(info, removed_tag, added_tag): assert_not_equal(removed_tag, added_tag) remove(info, removed_tag) add(info, added_tag) def check(info, tag): del info if tag not in changelog_tags: raise AssertionError('tag not in changelog: ' + tag) if tag not in data_tags: raise AssertionError('changelog adds unknown tag: ' + tag) for summary in reversed(summaries): match = summary_details_re.match(summary) for key, lines in match.groupdict().items(): if lines is None: continue lines = [l[8:] for l in lines.splitlines()] if key == 'added': for tag in lines: yield add, 'add', tag elif key == 'renamed': for line in lines: added_tag, removed_tag = rename_re.match(line).groups() yield rename, 'rename', removed_tag, added_tag else: assert False data_tags = frozenset(tag.name for tag in lib.tags.iter_tags()) for tag in sorted(changelog_tags | data_tags): yield check, 'check', tag def test_trailing_whitespace(): path = os.path.join(docdir, 'changelog') unreleased = False with open(path, 'rt', encoding='UTF-8') as file: for n, line in enumerate(file, 1): if n == 1 and ' UNRELEASED;' in line: unreleased = True if n == 3 and unreleased and line == ' * \n': continue line = line.rstrip('\n') if line[-1:].isspace(): raise AssertionError('trailing whitespace at line {0}'.format(n)) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/test_domains.py0000644000000000000000000000645113733665553020051 0ustar00rootroot00000000000000# Copyright © 2014-2016 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_is, assert_raises, assert_true, ) import lib.domains as M class test_special_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_special_domain_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') class test_dotless_domains: def t(self, domain, dotless=True): result = M.is_dotless_domain(domain) assert_is(result, dotless) def test_dotless(self): self.t('net') def test_dotfull(self): self.t('jwilk.net', False) self.t('example.jwilk.net', False) class test_dotless_emails: def t(self, email, dotless=True): result = M.is_email_in_dotless_domain(email) assert_is(result, dotless) def test_dotless(self): self.t('jwilk@net') def test_dotfull(self): self.t('jwilk@example.net', False) def test_no_at(self): with assert_raises(ValueError): self.t('jwilk%jwilk.net') # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/test_encodings.py0000644000000000000000000002046313733665553020367 0ustar00rootroot00000000000000# Copyright © 2012-2017 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, ) import lib.encodings as E from . import tools 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 t(encoding, expected_portable_encoding): portable_encoding = E.propose_portable_encoding(encoding) assert_equal(portable_encoding, expected_portable_encoding) yield t, 'ISO8859-2', 'ISO-8859-2' yield t, 'ISO_8859-2', 'ISO-8859-2' yield t, 'Windows-1250', 'CP1250' def test_notfound(self): portable_encoding = E.propose_portable_encoding('ISO-8859-16') assert_is_none(portable_encoding) class test_ascii_compatibility: def test_portable(self): def t(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 t, encoding def test_incompatible(self): def t(encoding): assert_false(E.is_ascii_compatible_encoding(encoding)) assert_false(E.is_ascii_compatible_encoding(encoding, missing_ok=False)) yield t, 'UTF-7' yield t, '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): t = self._test_missing yield t, 'base64_codec' yield t, 'bz2_codec' yield t, 'hex_codec' yield t, 'quopri_codec' yield t, 'rot_13' yield t, 'uu_codec' yield t, '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: @tools.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() @tools.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) @tools.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' @tools.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) @tools.fork_isolation def test_8b_encode_error(self): E.install_extra_encodings() u = self._viscii_unicode with assert_raises(UnicodeEncodeError): u.encode('KOI8-RU') @tools.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) @tools.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' @tools.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) @tools.fork_isolation def test_mb_encode_error(self): E.install_extra_encodings() u = self._viscii_unicode with assert_raises(UnicodeEncodeError): u.encode('EUC-TW') @tools.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) @tools.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 sts=4 sw=4 et i18nspector-0.26/tests/test_gettext.py0000644000000000000000000005435413733665553020110 0ustar00rootroot00000000000000# Copyright © 2012-2020 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_no_trailing_nl(self): self.t( 'Menu: spam\nVikings: yes', [{'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_badly_nested_conditional(self): with assert_raises(self.error): self.t('2 ? (3 : 7 ? ) : 23') def test_unary_minus(self): with assert_raises(self.error): self.t('-37') with assert_raises(self.error): self.t('23 + (-37)') def test_unary_plus(self): with assert_raises(self.error): self.t('+42') with assert_raises(self.error): self.t('23 + (+37)') def test_func_call(self): with assert_raises(self.error): self.t('n(42)') with assert_raises(self.error): self.t('42(n)') def test_unbalanced_parentheses(self): with assert_raises(self.error): self.t('(6 * 7') 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_shift(self): with assert_raises(self.error): self.t('6 << 7') with assert_raises(self.error): self.t('6 >> 7') def test_pow(self): with assert_raises(self.error): self.t('6 ** 7') def test_floor_div(self): with assert_raises(self.error): self.t('6 // 7') def test_tuple(self): with assert_raises(self.error): self.t('()') with assert_raises(self.error): self.t('(6, 7)') def test_starred(self): with assert_raises(self.error): self.t('*42') def test_exotic_whitespace(self): with assert_raises(self.error): self.t('6 *\xA07') def test_empty(self): with assert_raises(self.error): self.t('') with assert_raises(self.error): self.t(' ') 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_branches_ok(self): self.t('n ? 37 : 42', 37, 42) self.t( 'n ? (6 + n%23) : (7 + n%37)', 6, 37 + 7 - 1 ) class test_period: def t(self, s, offset, period=None): f = M.parse_plural_expression(s) op = f.period() if offset is None: assert period is None assert_is_none(op) else: assert_equal(op, (offset, period)) def test_num(self): self.t('42', 0, 1) def test_const_mod(self): self.t('n % 42', 0, 42) self.t('n % 0', None) def test_binop(self): self.t('n + (n % 37)', None) self.t('(n % 37) + n', None) self.t('(n % 6) + (n % 14)', 0, 42) self.t('(n % 641) * (n % 6700417)', None) # overflow def test_unaryop(self): self.t('!n', None) self.t('!(n % 37)', 0, 37) def _cmp_shift(self, op): def e(n, op, m): return eval(str(n) + op + str(m)) # pylint: disable=eval-used return e(0, op, 0) != e(1, op, 0) def test_const_cmp(self): for op in {'!=', '==', '<', '<=', '>', '>='}: shift = self._cmp_shift(op) self.t('n {op} {i}'.format(op=op, i=37), 37 + shift, 1) def test_const_cmp_overflow(self): ops = {'!=', '==', '<', '<=', '>', '>='} m = (1 << 32) - 1 for op in ops: shift = self._cmp_shift(op) self.t('n {op} {m}'.format(op=op, m=(m - 1)), m - 1 + shift, 1) if shift: self.t('n {op} {m}'.format(op=op, m=m), None) else: self.t('n {op} {m}'.format(op=op, m=m), m, 1) self.t('n {op} {m}'.format(op=op, m=(m + 1)), None) self.t('n {op} {m}'.format(op=op, m=(m + 42)), None) def test_compare(self): self.t('n < (n % 37)', None) self.t('(n % 37) < n', None) self.t('(n % 6) < (n % 14)', 0, 42) self.t('(n % 641) < (n % 6700417)', None) # overflow def test_boolop(self): self.t('n && (n % 37)', None) self.t('(n % 37) && n', None) self.t('(n % 6) && (n % 14)', 0, 42) self.t('(n % 641) && (n % 6700417)', None) # overflow def test_ifexp(self): self.t('n ? (n % 3) : (n % 7)', None) self.t('(n % 2) ? n : (n % 7)', None) self.t('(n % 2) ? (n % 3) : n', None) self.t('(n % 2) ? (n % 3) : (n % 7)', 0, 42) self.t('(n % 2) ? (n % 3) : (n % 715827883)', None) # overflow def test_num_overflow(self): m = (1 << 32) - 1 self.t(str(m), 0, 1) self.t(str(m + 1), None) self.t(str(m + 42), None) def test_real_world(self): self.t('0', 0, 1) self.t('n != 1', 2, 1) self.t('n > 1', 2, 1) self.t('n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3', 0, 100) self.t('n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2', 1, 100) self.t('n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2', 0, 100) self.t('n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2', 0, 100) self.t('n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2', 2, 100) self.t('n==1 ? 0 : (n>=2 && n<=4) ? 1 : 2', 5, 1) self.t('n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2', 2, 100) self.t('n==1 ? 0 : n==2 ? 1 : 2', 3, 1) self.t('n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2', 2, 100) class test_plural_forms: error = M.PluralFormsSyntaxError def t(self, s, *, n, ljunk='', rjunk=''): if ljunk or rjunk: with assert_raises(self.error): M.parse_plural_forms(s) else: (n0, expr0) = M.parse_plural_forms(s) del expr0 assert_equal(n0, n) (n1, expr1, ljunk1, rjunk1) = M.parse_plural_forms(s, strict=False) # pylint: disable=unbalanced-tuple-unpacking del expr1 assert_equal(n1, n) assert_equal(ljunk1, ljunk) assert_equal(rjunk1, rjunk) def test_nplurals_0(self): with assert_raises(self.error): self.t('nplurals=0; plural=0;', n=0) def test_nplurals_positive(self): for n in 1, 2, 10, 42: self.t('nplurals={}; plural=0;'.format(n), n=n) def test_missing_trailing_semicolon(self): self.t('nplurals=1; plural=0', n=1) def test_junk(self): self.t('eggsnplurals=1; plural=0;', n=1, ljunk='eggs') self.t('nplurals=1; plural=0;ham', n=1, rjunk='ham') self.t('baconnplurals=1; plural=0;spam', n=1, ljunk='bacon', rjunk='spam') 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_separator(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_abbrev(self): # OK: self.t( '2004-04-20 13:24+CEST', '2004-04-20 13:24+0200', ) 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_abbrev_ambiguous(self): self.t('2004-04-14 21:35+CDT', None) self.t('2000-06-14 23:23+EST', None) # XXX In tzdata 2014f, EST stands only for (US) Eastern Time Zone, i.e. # -0500. But in the previous version of tzdata it could also stand for # (Australian) Eastern Standard/Summer Time. # https://mm.icann.org/pipermail/tz/2014-June/021089.html def test_abbrev_nonexistent(self): self.t('2005-12-20 10:33+JEST', None) 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 = 28 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 sts=4 sw=4 et i18nspector-0.26/tests/test_iconv.py0000644000000000000000000000363713733665553017540 0ustar00rootroot00000000000000# Copyright © 2013-2019 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_raises, ) 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' def test_incomplete_char(): b = 'Ę'.encode('UTF-8')[:1] with assert_raises(UnicodeDecodeError): M.decode(b, 'UTF-8') # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/test_ling.py0000644000000000000000000004544413733665553017355 0ustar00rootroot00000000000000# Copyright © 2012-2017 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 nose 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, ) import lib.encodings import lib.ling from . import tools 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', '') def test_language_repr(): # Language.__repr__() is never used by i18nspector itself, # but it's useful for debugging test failures. lng = T('el') assert_equal(repr(lng), '') 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_lone_comma(self): with assert_raises(LookupError): self.t(',', None) 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) @tools.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, []) def test_glibc_supported(): def t(l): lang = L.parse_language(l) try: lang.fix_codes() except L.FixingLanguageCodesFailed: # FIXME: some ISO-639-3 codes are not recognized yet if len(l.split('_')[0]) == 3: raise nose.SkipTest('expected failure') reason = locales_to_skip.get(l) if reason is not None: raise nose.SkipTest(reason) raise assert_equal(str(lang), l) try: file = open('/usr/share/i18n/SUPPORTED', encoding='ASCII') except OSError as exc: raise nose.SkipTest(exc) locales = set() with file: for line in file: if line[:1] in {'#', '\n'}: continue locale, *rest = line.split() del rest if (locale + '.').startswith('iw_IL.'): # iw_IL is obsolete continue locales.add(locale) misnamed_locales = { # glibc 2.21 had two misnamed locales: 'bh_IN.UTF-8', # should be bhb_IN 'tu_IN.UTF-8', # should be tcy_IN } locales_to_skip = {} if locales & misnamed_locales == misnamed_locales: for l in misnamed_locales: locales_to_skip[l] = 'https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=032c510db06c' for l in sorted(locales): yield t, l def test_poedit(): # https://github.com/vslavik/poedit/blob/v1.8.1-oss/src/language_impl_legacy.h # There won't be any new names in this table, # so it's safe to hardcode them all here. def t(name, poedit_ll): poedit_ll = L.parse_language(poedit_ll) ll = L.get_language_for_name(name) assert_equal(ll, poedit_ll) def x(name, poedit_ll): poedit_ll = L.parse_language(poedit_ll) with assert_raises(LookupError): L.get_language_for_name(name) raise nose.SkipTest('expected failure') yield t, 'Abkhazian', 'ab' yield t, 'Afar', 'aa' yield t, 'Afrikaans', 'af' yield t, 'Albanian', 'sq' yield t, 'Amharic', 'am' yield t, 'Arabic', 'ar' yield t, 'Armenian', 'hy' yield t, 'Assamese', 'as' yield t, 'Avestan', 'ae' yield t, 'Aymara', 'ay' yield t, 'Azerbaijani', 'az' yield t, 'Bashkir', 'ba' yield t, 'Basque', 'eu' yield t, 'Belarusian', 'be' yield t, 'Bengali', 'bn' yield t, 'Bislama', 'bi' yield t, 'Bosnian', 'bs' yield t, 'Breton', 'br' yield t, 'Bulgarian', 'bg' yield t, 'Burmese', 'my' yield t, 'Catalan', 'ca' yield t, 'Chamorro', 'ch' yield t, 'Chechen', 'ce' yield t, 'Chichewa; Nyanja', 'ny' yield t, 'Chinese', 'zh' yield t, 'Church Slavic', 'cu' yield t, 'Chuvash', 'cv' yield t, 'Cornish', 'kw' yield t, 'Corsican', 'co' yield t, 'Croatian', 'hr' yield t, 'Czech', 'cs' yield t, 'Danish', 'da' yield t, 'Dutch', 'nl' yield t, 'Dzongkha', 'dz' yield t, 'English', 'en' yield t, 'Esperanto', 'eo' yield t, 'Estonian', 'et' yield t, 'Faroese', 'fo' yield t, 'Fijian', 'fj' yield t, 'Finnish', 'fi' yield t, 'French', 'fr' yield t, 'Frisian', 'fy' yield t, 'Friulian', 'fur' yield t, 'Gaelic', 'gd' yield t, 'Galician', 'gl' yield t, 'Georgian', 'ka' yield t, 'German', 'de' yield t, 'Greek', 'el' yield t, 'Guarani', 'gn' yield t, 'Gujarati', 'gu' yield t, 'Hausa', 'ha' yield t, 'Hebrew', 'he' yield t, 'Herero', 'hz' yield t, 'Hindi', 'hi' yield t, 'Hiri Motu', 'ho' yield t, 'Hungarian', 'hu' yield t, 'Icelandic', 'is' yield t, 'Indonesian', 'id' yield t, 'Interlingua', 'ia' yield t, 'Interlingue', 'ie' yield t, 'Inuktitut', 'iu' yield t, 'Inupiaq', 'ik' yield t, 'Irish', 'ga' yield t, 'Italian', 'it' yield t, 'Japanese', 'ja' yield t, 'Javanese', 'jv' # https://github.com/vslavik/poedit/pull/193 yield t, 'Kalaallisut', 'kl' yield t, 'Kannada', 'kn' yield t, 'Kashmiri', 'ks' yield t, 'Kazakh', 'kk' yield t, 'Khmer', 'km' yield t, 'Kikuyu', 'ki' yield t, 'Kinyarwanda', 'rw' yield t, 'Komi', 'kv' yield t, 'Korean', 'ko' yield t, 'Kuanyama', 'kj' yield t, 'Kurdish', 'ku' yield t, 'Kyrgyz', 'ky' yield t, 'Lao', 'lo' yield t, 'Latin', 'la' yield t, 'Latvian', 'lv' yield t, 'Letzeburgesch', 'lb' yield t, 'Lingala', 'ln' yield t, 'Lithuanian', 'lt' yield t, 'Macedonian', 'mk' yield t, 'Malagasy', 'mg' yield t, 'Malay', 'ms' yield t, 'Malayalam', 'ml' yield t, 'Maltese', 'mt' yield t, 'Maori', 'mi' yield t, 'Marathi', 'mr' yield t, 'Marshall', 'mh' yield t, 'Moldavian', 'ro_MD' # XXX poedit uses deprecated "mo" yield t, 'Mongolian', 'mn' yield t, 'Nauru', 'na' yield t, 'Navajo', 'nv' yield t, 'Ndebele, South', 'nr' yield t, 'Ndonga', 'ng' yield t, 'Nepali', 'ne' yield t, 'Northern Sami', 'se' yield t, 'Norwegian Bokmal', 'nb' yield t, 'Norwegian Nynorsk', 'nn' yield t, 'Occitan', 'oc' yield t, 'Oriya', 'or' yield t, 'Ossetian; Ossetic', 'os' yield t, 'Pali', 'pi' yield t, 'Panjabi', 'pa' yield t, 'Pashto, Pushto', 'ps' yield t, 'Persian', 'fa' yield t, 'Polish', 'pl' yield t, 'Portuguese', 'pt' yield t, 'Quechua', 'qu' yield t, 'Rhaeto-Romance', 'rm' yield t, 'Romanian', 'ro' yield t, 'Rundi', 'rn' yield t, 'Russian', 'ru' yield t, 'Samoan', 'sm' yield t, 'Sangro', 'sg' yield t, 'Sanskrit', 'sa' yield t, 'Sardinian', 'sc' yield t, 'Serbian', 'sr' yield t, 'Sesotho', 'st' yield t, 'Setswana', 'tn' yield t, 'Shona', 'sn' yield t, 'Sindhi', 'sd' yield t, 'Sinhalese', 'si' yield t, 'Siswati', 'ss' yield t, 'Slovak', 'sk' yield t, 'Slovenian', 'sl' yield t, 'Somali', 'so' yield t, 'Spanish', 'es' yield t, 'Sundanese', 'su' yield t, 'Swahili', 'sw' yield t, 'Swedish', 'sv' yield t, 'Tagalog', 'tl' yield t, 'Tahitian', 'ty' yield t, 'Tajik', 'tg' yield t, 'Tamil', 'ta' yield t, 'Tatar', 'tt' yield t, 'Telugu', 'te' yield t, 'Thai', 'th' yield t, 'Tibetan', 'bo' yield t, 'Tigrinya', 'ti' yield t, 'Tonga', 'to' yield t, 'Tsonga', 'ts' yield t, 'Turkish', 'tr' yield t, 'Turkmen', 'tk' yield t, 'Twi', 'tw' yield t, 'Ukrainian', 'uk' yield t, 'Urdu', 'ur' yield t, 'Uyghur', 'ug' yield t, 'Uzbek', 'uz' yield t, 'Vietnamese', 'vi' yield t, 'Volapuk', 'vo' yield t, 'Walloon', 'wa' yield t, 'Welsh', 'cy' yield t, 'Wolof', 'wo' yield t, 'Xhosa', 'xh' yield t, 'Yiddish', 'yi' yield t, 'Yoruba', 'yo' yield t, 'Zhuang', 'za' yield t, 'Zulu', 'zu' # TODO: yield x, '(Afan) Oromo', 'om' yield x, 'Bihari', 'bh' # "bh" is marked as collective in ISO-639-2 yield x, 'Serbian (Latin)', 'sr_RS@latin' yield x, 'Serbo-Croatian', 'sh' # "sh" is deprecated in favor of "sr", "hr", "bs" # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/test_misc.py0000644000000000000000000001013413733665553017343 0ustar00rootroot00000000000000# Copyright © 2012-2017 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 stat import tempfile import time from nose.tools import ( assert_almost_equal, assert_equal, assert_is_instance, assert_is_not_none, assert_raises, assert_true, ) import lib.misc as M from . import tools class test_unsorted: def t(self, lst, expected): assert_is_instance(lst, list) r = M.unsorted(lst) assert_equal(r, expected) r = M.unsorted(x for x in lst) assert_equal(r, expected) def test_0(self): self.t([], None) def test_1(self): self.t([17], None) def test_2(self): self.t([17, 23], None) self.t([23, 17], (23, 17)) def test_3(self): self.t([17, 23, 37], None) self.t([17, 37, 23], (37, 23)) self.t([23, 17, 37], (23, 17)) self.t([23, 37, 17], (37, 17)) self.t([37, 17, 23], (37, 17)) self.t([37, 23, 17], (37, 23)) def test_inf(self): def iterable(): yield 17 yield 37 while True: yield 23 r = M.unsorted(iterable()) assert_equal(r, (37, 23)) class test_check_sorted: def test_sorted(self): M.check_sorted([17, 23, 37]) def test_unsorted(self): with assert_raises(M.DataIntegrityError) as cm: M.check_sorted([23, 37, 17]) assert_equal(str(cm.exception), '37 > 17') def test_sorted_vk(): lst = ['eggs', 'spam', 'ham'] d = dict(enumerate(lst)) assert_equal( lst, list(M.sorted_vk(d)) ) class test_utc_now: def test_types(self): 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)) @tools.fork_isolation def test_tz_resistance(self): def t(tz): os.environ['TZ'] = tz time.tzset() return M.utc_now() now1 = t('Etc/GMT-4') now2 = t('Etc/GMT+2') tdelta = (now1 - now2).total_seconds() assert_almost_equal(tdelta, 0, delta=0.75) class test_format_range: def t(self, x, y, max, expected): # pylint: disable=redefined-builtin 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') def test_throwaway_tempdir(): with M.throwaway_tempdir('test'): d = tempfile.gettempdir() st = os.stat(d) assert_equal(stat.S_IMODE(st.st_mode), 0o700) assert_true(stat.S_ISDIR(st.st_mode)) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/test_moparser.py0000644000000000000000000000476013733665553020250 0ustar00rootroot00000000000000# Copyright © 2014-2017 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 random from nose.tools import ( assert_equal, assert_raises, ) import lib.moparser as M from . import tools def parser_for_bytes(data): with tools.temporary_file(suffix='.mo') as file: file.write(data) file.flush() return M.Parser(file.name) class test_magic: def test_value(self): assert_equal(M.little_endian_magic, b'\xDE\x12\x04\x95') assert_equal(M.big_endian_magic, b'\x95\x04\x12\xDE') def test_short(self): for j in range(0, 3): data = M.little_endian_magic[:j] with assert_raises(M.SyntaxError) as cm: parser_for_bytes(data) assert_equal(str(cm.exception), 'unexpected magic') def test_full(self): for magic in {M.little_endian_magic, M.big_endian_magic}: with assert_raises(M.SyntaxError) as cm: parser_for_bytes(magic) assert_equal(str(cm.exception), 'truncated file') def test_random(self): while True: random_magic = bytes( random.randrange(0, 0x100) for i in range(0, 4) ) if random_magic in {M.little_endian_magic, M.big_endian_magic}: continue break with assert_raises(M.SyntaxError) as cm: parser_for_bytes(random_magic) assert_equal(str(cm.exception), 'unexpected magic') # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/test_polib4us.py0000644000000000000000000000377413733665553020165 0ustar00rootroot00000000000000# Copyright © 2013-2017 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_list_equal, assert_true, ) import lib.polib4us as M from . import tools minimal_header = r''' msgid "" msgstr "Content-Type: text/plain; charset=US-ASCII\n" ''' class test_codecs: @tools.fork_isolation def test_trailing_obsolete_message(self): s = minimal_header + ''' msgid "a" msgstr "b" #~ msgid "b" #~ msgstr "c" ''' def t(): with tools.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() @tools.fork_isolation def test_flag_splitting(): M.install_patches() e = polib.POEntry() e.flags = ['fuzzy,c-format'] assert_list_equal( e.flags, ['fuzzy', 'c-format'] ) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/test_strformat_c.py0000644000000000000000000004017613733665553020744 0ustar00rootroot00000000000000# Copyright © 2014-2018 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 struct import sys import unittest.mock import nose from nose.tools import ( assert_equal, assert_greater, assert_is_instance, assert_raises, assert_sequence_equal, ) import lib.strformat.c as M def test_INT_MAX(): struct.pack('=i', M.INT_MAX) with assert_raises(struct.error): struct.pack('=i', M.INT_MAX + 1) def is_glibc(): try: os.confstr('CS_GNU_LIBC_VERSION') except (ValueError, OSError): return False return True def test_NL_ARGMAX(): plat = sys.platform if plat.startswith('linux') and is_glibc(): assert_equal( M.NL_ARGMAX, os.sysconf('SC_NL_ARGMAX') ) else: raise nose.SkipTest('Test specific to Linux with glibc') small_NL_ARGMAX = unittest.mock.patch('lib.strformat.c.NL_ARGMAX', 42) # Setting NL_ARGMAX to a small number makes the *_index_out_of_range() tests # much faster. def test_lone_percent(): with assert_raises(M.Error): M.FormatString('%') def test_invalid_conversion_spec(): with assert_raises(M.Error): M.FormatString('%!') def test_add_argument(): fmt = M.FormatString('%s') with assert_raises(RuntimeError): fmt.add_argument(2, None) def test_text(): fmt = M.FormatString('eggs%dbacon%dspam') assert_equal(len(fmt), 5) fmt = list(fmt) assert_equal(fmt[0], 'eggs') assert_equal(fmt[2], 'bacon') assert_equal(fmt[4], 'spam') class test_types: def t(self, s, tp, warn_type=None, integer=False): fmt = M.FormatString(s) [conv] = fmt assert_is_instance(conv, M.Conversion) assert_equal(conv.type, tp) if tp == 'void': assert_sequence_equal(fmt.arguments, []) else: [[arg]] = fmt.arguments assert_equal(arg.type, tp) if warn_type is None: assert_sequence_equal(fmt.warnings, []) else: [warning] = fmt.warnings assert_is_instance(warning, warn_type) assert_equal(conv.integer, integer) def test_integer(self): def t(s, tp, warn_type=None): integer = not suffix self.t(s, tp + suffix, warn_type, integer) for c in 'din': suffix = '' if c == 'n': suffix = ' *' yield t, ('%hh' + c), 'signed char' yield t, ('%h' + c), 'short int' yield t, ('%' + c), 'int' yield t, ('%l' + c), 'long int' yield t, ('%ll' + c), 'long long int' yield t, ('%L' + c), 'long long int', M.NonPortableConversion yield t, ('%q' + c), 'long long int', M.NonPortableConversion yield t, ('%j' + c), 'intmax_t' yield t, ('%z' + c), 'ssize_t' yield t, ('%Z' + c), 'ssize_t', M.NonPortableConversion yield t, ('%t' + c), 'ptrdiff_t' for c in 'ouxX': suffix = '' yield t, ('%hh' + c), 'unsigned char' yield t, ('%h' + c), 'unsigned short int' yield t, ('%' + c), 'unsigned int' yield t, ('%l' + c), 'unsigned long int' yield t, ('%ll' + c), 'unsigned long long int' yield t, ('%L' + c), 'unsigned long long int', M.NonPortableConversion yield t, ('%q' + c), 'unsigned long long int', M.NonPortableConversion yield t, ('%j' + c), 'uintmax_t' yield t, ('%z' + c), 'size_t' yield t, ('%Z' + c), 'size_t', M.NonPortableConversion yield t, ('%t' + c), '[unsigned ptrdiff_t]' def test_double(self): t = self.t for c in 'aefgAEFG': yield t, ('%' + c), 'double' yield t, ('%l' + c), 'double', M.NonPortableConversion yield t, ('%L' + c), 'long double' def test_char(self): t = self.t yield t, '%c', 'char' yield t, '%lc', 'wint_t' yield t, '%C', 'wint_t', M.NonPortableConversion yield t, '%s', 'const char *' yield t, '%ls', 'const wchar_t *' yield t, '%S', 'const wchar_t *', M.NonPortableConversion def test_void(self): t = self.t yield t, '%p', 'void *' yield t, '%m', 'void' yield t, '%%', 'void' def test_c99_macros(self): # pylint: disable=undefined-loop-variable def _t(s, tp): return self.t(s, tp, integer=True) def t(s, tp): return ( _t, '%<{macro}>'.format(macro=s.format(c=c, n=n)), ('u' if unsigned else '') + tp.format(n=n) ) # pylint: enable=undefined-loop-variable for c in 'diouxX': unsigned = c not in 'di' for n in {8, 16, 32, 64}: yield t('PRI{c}{n}', 'int{n}_t') yield t('PRI{c}LEAST{n}', 'int_least{n}_t') yield t('PRI{c}FAST{n}', 'int_fast{n}_t') yield t('PRI{c}MAX', 'intmax_t') yield t('PRI{c}PTR', 'intptr_t') class test_invalid_length: def t(self, s): with assert_raises(M.LengthError): M.FormatString(s) _lengths = ['hh', 'h', 'l', 'll', 'q', 'j', 'z', 't', 'L'] def test_double(self): t = self.t for c in 'aefgAEFG': for l in self._lengths: if l in 'lL': continue yield t, ('%' + l + c) def test_char(self): t = self.t for c in 'cs': for l in self._lengths: if l != 'l': yield t, '%' + l + c yield t, ('%' + l + c.upper()) def test_void(self): t = self.t for c in 'pm%': for l in self._lengths: yield t, ('%' + l + c) class test_numeration: def test_percent(self): with assert_raises(M.ForbiddenArgumentIndex): M.FormatString('%1$%') def test_errno(self): # FIXME? fmt = M.FormatString('%1$m') assert_equal(len(fmt), 1) assert_equal(len(fmt.arguments), 0) def test_swapped(self): fmt = M.FormatString('%2$s%1$d') assert_equal(len(fmt), 2) [a1], [a2] = fmt.arguments assert_equal(a1.type, 'int') assert_equal(a2.type, 'const char *') def test_numbering_mixture(self): def t(s): with assert_raises(M.ArgumentNumberingMixture): M.FormatString(s) t('%s%2$s') t('%2$s%s') @small_NL_ARGMAX def test_index_out_of_range(self): with assert_raises(M.ArgumentRangeError): M.FormatString('%0$d') def fs(n): s = ''.join( '%{0}$d'.format(i) for i in range(1, n + 1) ) return M.FormatString(s) fmt = fs(M.NL_ARGMAX) assert_equal(len(fmt), M.NL_ARGMAX) assert_equal(len(fmt.arguments), M.NL_ARGMAX) with assert_raises(M.ArgumentRangeError): fs(M.NL_ARGMAX + 1) def test_initial_gap(self): with assert_raises(M.MissingArgument): M.FormatString('%2$d') def test_gap(self): with assert_raises(M.MissingArgument): M.FormatString('%3$d%1$d') class test_redundant_flag: def t(self, s): fmt = M.FormatString(s) [exc] = fmt.warnings assert_is_instance(exc, M.RedundantFlag) def test_duplicate(self): self.t('%--17d') def test_minus_zero(self): self.t('%-017d') def test_plus_space(self): self.t('%+ d') # TODO: Check for other redundant flags, for example “%+s”. class test_expected_flag: def t(self, s): fmt = M.FormatString(s) assert_equal(len(fmt), 1) def test_hash(self): for c in 'oxXaAeEfFgG': yield self.t, ('%#' + c) def test_zero(self): for c in 'diouxXaAeEfFgG': yield self.t, ('%0' + c) def test_apos(self): for c in 'diufFgG': yield self.t, ("%'" + c) def test_other(self): for flag in '- +I': for c in 'diouxXaAeEfFgGcCsSpm': yield self.t, ('%' + flag + c) class test_unexpected_flag: def t(self, s): with assert_raises(M.FlagError): M.FormatString(s) def test_hash(self): for c in 'dicCsSnpm%': yield self.t, ('%#' + c) def test_zero(self): for c in 'cCsSnpm%': yield self.t, ('%0' + c) def test_apos(self): for c in 'oxXaAeEcCsSnpm%': yield self.t, ("%'" + c) def test_other(self): for c in '%n': for flag in '- +I': yield self.t, ('%' + flag + c) class test_width: def test_ok(self): def t(s): fmt = M.FormatString(s) assert_equal(len(fmt), 1) for c in 'diouxXaAeEfFgGcCsSp': yield t, ('%1' + c) yield t, '%1m' # FIXME? def test_invalid(self): for c in '%n': with assert_raises(M.WidthError): M.FormatString('%1' + c) def test_too_large(self): fmt = M.FormatString('%{0}d'.format(M.INT_MAX)) assert_equal(len(fmt), 1) assert_equal(len(fmt.arguments), 1) with assert_raises(M.WidthRangeError): M.FormatString('%{0}d'.format(M.INT_MAX + 1)) def test_variable(self): fmt = M.FormatString('%*s') assert_equal(len(fmt), 1) assert_equal(len(fmt.arguments), 2) [a1], [a2] = fmt.arguments assert_equal(a1.type, 'int') assert_equal(a2.type, 'const char *') def _test_index(self, i): fmt = M.FormatString('%2$*{0}$s'.format(i)) assert_equal(len(fmt), 1) assert_equal(len(fmt.arguments), 2) [a1], [a2] = fmt.arguments assert_equal(a1.type, 'int') assert_equal(a2.type, 'const char *') def test_index(self): self._test_index(1) def test_leading_zero_index(self): self._test_index('01') self._test_index('001') @small_NL_ARGMAX def test_index_out_of_range(self): with assert_raises(M.ArgumentRangeError): M.FormatString('%1$*0$s') def fs(n): s = ''.join( '%{0}$d'.format(i) for i in range(2, n) ) + '%1$*{0}$s'.format(n) return M.FormatString(s) fmt = fs(M.NL_ARGMAX) assert_equal(len(fmt), M.NL_ARGMAX - 1) assert_equal(len(fmt.arguments), M.NL_ARGMAX) with assert_raises(M.ArgumentRangeError): fs(M.NL_ARGMAX + 1) def test_numbering_mixture(self): def t(s): with assert_raises(M.ArgumentNumberingMixture): M.FormatString(s) t('%1$*s') t('%*1$s') t('%s%1$*2$s') t('%1$*2$s%s') class test_precision: def test_ok(self): def t(s): fmt = M.FormatString(s) assert_equal(len(fmt), 1) for c in 'diouxXaAeEfFgGsS': yield t, ('%.1' + c) def test_redundant_0(self): def t(s): fmt = M.FormatString(s) assert_equal(len(fmt), 1) [warning] = fmt.warnings assert_is_instance(warning, M.RedundantFlag) for c in 'diouxX': yield t, ('%0.1' + c) def test_non_redundant_0(self): def t(s): fmt = M.FormatString(s) assert_equal(len(fmt), 1) assert_sequence_equal(fmt.warnings, []) for c in 'aAeEfFgG': yield t, ('%0.1' + c) def test_unexpected(self): def t(s): with assert_raises(M.PrecisionError): M.FormatString(s) for c in 'cCpnm%': yield t, ('%.1' + c) def test_too_large(self): fmt = M.FormatString('%.{0}f'.format(M.INT_MAX)) assert_equal(len(fmt), 1) with assert_raises(M.PrecisionRangeError): M.FormatString('%.{0}f'.format(M.INT_MAX + 1)) def test_variable(self): fmt = M.FormatString('%.*f') assert_equal(len(fmt), 1) assert_equal(len(fmt.arguments), 2) [a1], [a2] = fmt.arguments assert_equal(a1.type, 'int') assert_equal(a2.type, 'double') def _test_index(self, i): fmt = M.FormatString('%2$.*{0}$f'.format(i)) assert_equal(len(fmt), 1) assert_equal(len(fmt.arguments), 2) [a1], [a2] = fmt.arguments assert_equal(a1.type, 'int') assert_equal(a2.type, 'double') def test_index(self): self._test_index(1) def test_leading_zero_index(self): self._test_index('01') self._test_index('001') @small_NL_ARGMAX def test_index_out_of_range(self): with assert_raises(M.ArgumentRangeError): M.FormatString('%1$.*0$f') def fs(n): s = ''.join( '%{0}$d'.format(i) for i in range(2, n) ) + '%1$.*{0}$f'.format(n) return M.FormatString(s) fmt = fs(M.NL_ARGMAX) assert_equal(len(fmt), M.NL_ARGMAX - 1) assert_equal(len(fmt.arguments), M.NL_ARGMAX) with assert_raises(M.ArgumentRangeError): fs(M.NL_ARGMAX + 1) def test_numbering_mixture(self): def t(s): with assert_raises(M.ArgumentNumberingMixture): M.FormatString(s) t('%1$.*f') t('%.*1$f') t('%f%2$.*1$f') t('%2$.*1$f%f') class test_type_compatibility: def test_okay(self): def t(s, tp): fmt = M.FormatString(s) [args] = fmt.arguments assert_greater(len(args), 1) for arg in args: assert_equal(arg.type, tp) t('%1$d%1$d', 'int') t('%1$d%1$i', 'int') def test_mismatch(self): def t(s): with assert_raises(M.ArgumentTypeMismatch): M.FormatString(s) t('%1$d%1$hd') t('%1$d%1$u') t('%1$d%1$s') @small_NL_ARGMAX def test_too_many_conversions(): def t(s): with assert_raises(M.ArgumentRangeError): M.FormatString(s) s = M.NL_ARGMAX * '%d' fmt = M.FormatString(s) assert_equal(len(fmt), M.NL_ARGMAX) t(s + '%f') t(s + '%*f') t(s + '%.*f') class test_get_last_integer_conversion: def test_overflow(self): fmt = M.FormatString('%s%d') for n in [-1, 0, 3]: with assert_raises(IndexError): fmt.get_last_integer_conversion(n=n) def t(self, s, n, tp=M.Conversion): fmt = M.FormatString(s) conv = fmt.get_last_integer_conversion(n=n) if tp is None: tp = type(tp) assert_is_instance(conv, tp) return conv def test_okay(self): self.t('%d', 1) self.t('%s%d', 1) def test_non_integer(self): self.t('%s', 1, None) self.t('%c', 1, None) def test_too_many(self): self.t('%s%d', 2, None) self.t('%d%d', 2, None) def test_var(self): self.t('%*d', 1) self.t('%*d', 2) self.t('%.*d', 2) self.t('%1$*2$d', 2) self.t('%2$*3$.*1$d', 3) def test_broken_var(self): self.t('%1$*2$d', 1, None) self.t('%1$*2$d%3$d', 2, None) self.t('%1$*3$d%2$d', 2, None) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/test_strformat_perlbrace.py0000644000000000000000000000352613733665553022457 0ustar00rootroot00000000000000# Copyright © 2016-2020 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_raises, ) import lib.strformat.perlbrace as M def test_lone_lcb(): with assert_raises(M.Error): M.FormatString('{') def test_lone_rcb(): M.FormatString('}') def test_invalid_field(): with assert_raises(M.Error): M.FormatString('{@}') def test_text(): fmt = M.FormatString('bacon') assert_equal(len(fmt), 1) [fld] = fmt assert_equal(fld, 'bacon') class test_named_arguments: def test_good(self): fmt = M.FormatString('{spam}') assert_equal(len(fmt), 1) [fld] = fmt assert_equal(fld, '{spam}') def test_bad(self): with assert_raises(M.Error): M.FormatString('{3ggs}') # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/test_strformat_pybrace.py0000644000000000000000000002137113733665553022143 0ustar00rootroot00000000000000# Copyright © 2016-2018 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 struct import unittest.mock from nose.tools import ( assert_equal, assert_is, assert_is_instance, assert_raises, ) import lib.strformat.pybrace as M def test_SSIZE_MAX(): struct.pack('=i', M.SSIZE_MAX) with assert_raises(struct.error): struct.pack('=i', M.SSIZE_MAX + 1) small_SSIZE_MAX = unittest.mock.patch('lib.strformat.pybrace.SSIZE_MAX', 42) # Setting SSIZE_ARGMAX to a small number makes it possible to test for # a very large number of arguments without running out of memory. def test_lone_lcb(): with assert_raises(M.Error): M.FormatString('{') def test_lone_rcb(): with assert_raises(M.Error): M.FormatString('}') def test_invalid_field(): with assert_raises(M.Error): M.FormatString('{@}') def test_add_argument(): fmt = M.FormatString('{}') with assert_raises(RuntimeError): fmt.add_argument(None, None) with assert_raises(RuntimeError): fmt.add_argument('eggs', None) def test_text(): fmt = M.FormatString('eggs{}bacon{}spam') assert_equal(len(fmt), 5) fmt = list(fmt) assert_equal(fmt[0], 'eggs') assert_equal(fmt[2], 'bacon') assert_equal(fmt[4], 'spam') class test_types: def t(self, k, *types): types = frozenset(tp.__name__ for tp in types) fmt = M.FormatString('{:' + k + '}') [fld] = fmt assert_is_instance(fld, M.Field) assert_equal(fld.types, types) assert_equal(len(fmt.argument_map), 1) [(key, [afld])] = fmt.argument_map.items() assert_equal(key, 0) assert_is(fld, afld) def test_default(self): self.t('', int, float, str) def test_s(self): self.t('s', str) def test_int(self): for k in 'bcdoxX': self.t(k, int) def test_n(self): self.t('n', int, float) def test_float(self): for k in 'eEfFgG': self.t(k, float) class test_conversion: def t(self, c, k, *types): types = frozenset(tp.__name__ for tp in types) fmt = M.FormatString('{!' + c + ':' + k + '}') [fld] = fmt assert_is_instance(fld, M.Field) assert_equal(fld.types, types) assert_equal(len(fmt.argument_map), 1) [(key, [afld])] = fmt.argument_map.items() assert_equal(key, 0) assert_is(fld, afld) def test_default(self): for c in 'sra': self.t(c, '', int, float, str) def test_s(self): for c in 'sra': self.t(c, 's', str) def test_numeric(self): for c in 'sra': for k in 'bcdoxXneEfFgG': with assert_raises(M.FormatTypeMismatch): self.t(c, k, int) def test_bad(self): with assert_raises(M.ConversionError): self.t('z', '') class test_numbered_arguments: tp_int = frozenset({'int'}) tp_float = frozenset({'float'}) def t(self, s, *types): fmt = M.FormatString(s) assert_equal(len(fmt), len(types)) assert_equal(len(fmt.argument_map), len(types)) for (key, args), (xkey, xtype) in zip(sorted(fmt.argument_map.items()), enumerate(types)): [arg] = args assert_equal(key, xkey) assert_equal(arg.types, frozenset({xtype.__name__})) def test_unnumbered(self): self.t('{:d}{:f}', int, float) def test_numbered(self): self.t('{0:d}{1:f}', int, float) def test_swapped(self): self.t('{1:d}{0:f}', float, int) def test_mixed(self): with assert_raises(M.ArgumentNumberingMixture): self.t('{0:d}{:f}') with assert_raises(M.ArgumentNumberingMixture): self.t('{:d}{0:f}') def test_numbered_out_of_range(self): def t(i): s = ('{' + str(i) + '}') M.FormatString(s) t(M.SSIZE_MAX) with assert_raises(M.ArgumentRangeError): t(M.SSIZE_MAX + 1) @small_SSIZE_MAX def test_unnumbered_out_of_range(self): def t(i): s = '{}' * i M.FormatString(s) t(M.SSIZE_MAX + 1) with assert_raises(M.ArgumentRangeError): t(M.SSIZE_MAX + 2) class test_named_arguments: def test_good(self): fmt = M.FormatString('{spam}') [fld] = fmt [(aname, [afld])] = fmt.argument_map.items() assert_equal(aname, 'spam') assert_is(fld, afld) def test_bad(self): with assert_raises(M.Error): M.FormatString('{3ggs}') class test_format_spec: def test_bad_char(self): with assert_raises(M.Error): M.FormatString('{:@}') def test_bad_letter(self): with assert_raises(M.Error): M.FormatString('{:Z}') def test_comma(self): def t(k): M.FormatString('{:,' + k + '}') t('') for k in 'bcdoxXeEfFgG': t(k) for k in 'ns': with assert_raises(M.Error): t(k) def test_alt_sign(self): def t(c, k): M.FormatString('{:' + c + k + '}') for c in ' +-#': t(c, '') for k in 'bcdoxXneEfFgG': t(c, k) with assert_raises(M.Error): t(c, 's') def test_align(self): def t(c, k): M.FormatString('{:' + c + k + '}') for c in '<>^': t(c, '') for k in 'bcdoxXneEfFgGs': t(c, k) t(c + '0', k) for c in '=0': t(c, '') for k in 'bcdoxXneEfFgG': t(c, k) with assert_raises(M.Error): t(c, 's') def test_width(self): def t(w, k): if k == '\0': k = '' M.FormatString('{:' + str(w) + k + '}') for k in 'bcdoxXneEfFgGs\0': for i in 4, 37, M.SSIZE_MAX: t(i, k) with assert_raises(M.Error): t(M.SSIZE_MAX + 1, k) def test_precision(self): def t(w, k): if k == '\0': k = '' M.FormatString('{:.' + str(w) + k + '}') for k in 'neEfFgGs\0': for i in {4, 37, M.SSIZE_MAX}: t(i, k) with assert_raises(M.Error): t(M.SSIZE_MAX + 1, k) for k in 'bcdoxX': for i in {4, 37, M.SSIZE_MAX, M.SSIZE_MAX + 1}: with assert_raises(M.Error): t(i, k) def test_type_compat(self): def t(k1, k2): s = '{0:' + k1 + '}{0:' + k2 + '}' M.FormatString(s) def e(k1, k2): with assert_raises(M.ArgumentTypeMismatch): t(k1, k2) ks = 'bcdoxXneEfFgGs' compat = [ ('s', 's'), ('bcdoxX', 'bcdoxXn'), ('n', 'bcdoxXneEfFgG'), ('eEfFgG', 'neEfFgG'), ] for k in ks: t(k, '') t('', k) for (k1s, k2s) in compat: for k1 in k1s: for k2 in k2s: t(k1, k2) for k2 in ks: if k2 not in k2s: e(k1, k2) def test_nested_fields(self): def t(v=None, f=None): if v is None: v = '' if f is None: f = '' s = '{' + str(v) + ':{' + str(f) + '}}' return M.FormatString(s) fmt = t() assert_equal(len(fmt.argument_map), 2) t(v=0, f=M.SSIZE_MAX) with assert_raises(M.ArgumentRangeError): t(v=0, f=(M.SSIZE_MAX + 1)) with assert_raises(M.ArgumentNumberingMixture): t(v=0) with assert_raises(M.ArgumentNumberingMixture): t(f=0) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/test_strformat_python.py0000644000000000000000000002107013733665553022033 0ustar00rootroot00000000000000# Copyright © 2014-2016 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 struct from nose.tools import ( assert_equal, assert_greater, assert_is_instance, assert_raises, assert_sequence_equal, ) import lib.strformat.python as M def test_SSIZE_MAX(): struct.pack('=i', M.SSIZE_MAX) with assert_raises(struct.error): struct.pack('=i', M.SSIZE_MAX + 1) def test_lone_percent(): with assert_raises(M.Error): M.FormatString('%') def test_invalid_conversion_spec(): with assert_raises(M.Error): M.FormatString('%!') def test_add_argument(): fmt = M.FormatString('%s') with assert_raises(RuntimeError): fmt.add_argument(None, None) with assert_raises(RuntimeError): fmt.add_argument('eggs', None) def test_text(): fmt = M.FormatString('eggs%dbacon%dspam') assert_equal(len(fmt), 5) fmt = list(fmt) assert_equal(fmt[0], 'eggs') assert_equal(fmt[2], 'bacon') assert_equal(fmt[4], 'spam') class test_map: def t(self, key): s = '%(' + key + ')s' fmt = M.FormatString(s) assert_equal(len(fmt), 1) assert_sequence_equal(fmt.seq_arguments, []) [pkey] = fmt.map_arguments.keys() assert_equal(key, pkey) def test_simple(self): self.t('eggs') def test_balanced_parens(self): self.t('eggs(ham)spam') def test_unbalanced_parens(self): with assert_raises(M.Error): self.t('eggs(ham') class test_types: def t(self, s, tp, warn_type=None): fmt = M.FormatString(s) [conv] = fmt assert_is_instance(conv, M.Conversion) assert_equal(conv.type, tp) assert_equal(len(fmt.map_arguments), 0) if tp == 'None': assert_sequence_equal(fmt.seq_arguments, []) else: [arg] = fmt.seq_arguments assert_equal(arg.type, tp) if warn_type is None: assert_equal(len(fmt.warnings), 0) else: [warning] = fmt.warnings assert_is_instance(warning, warn_type) def test_integer(self): t = self.t for c in 'oxXdi': yield t, '%' + c, 'int' yield t, '%u', 'int', M.ObsoleteConversion def test_float(self): t = self.t for c in 'eEfFgG': yield t, '%' + c, 'float' def test_str(self): t = self.t yield t, '%c', 'chr' yield t, '%s', 'str' def test_repr(self): t = self.t for c in 'ra': yield t, '%' + c, 'object' def test_void(self): yield self.t, '%%', 'None' def test_length(): def t(l): fmt = M.FormatString('%' + l + 'd') [warning] = fmt.warnings assert_is_instance(warning, M.RedundantLength) for l in 'hlL': yield t, l class test_indexing: def test_percent(self): with assert_raises(M.ForbiddenArgumentKey): M.FormatString('%(eggs)%') def test_indexing_mixture(self): def t(s): with assert_raises(M.ArgumentIndexingMixture): M.FormatString(s) t('%s%(eggs)s') t('%(eggs)s%s') # TODO: "u" should be everywhere, where "d" is class test_multiple_flags: def t(self, s): fmt = M.FormatString(s) [exc] = fmt.warnings assert_is_instance(exc, M.RedundantFlag) def test_duplicate(self): self.t('%--17d') def test_minus_zero(self): self.t('%-017d') def test_plus_space(self): self.t('%+ d') def test_single_flag(): def t(s, expected): fmt = M.FormatString(s) assert_equal(len(fmt), 1) if expected: assert_sequence_equal(fmt.warnings, []) else: [exc] = fmt.warnings assert_is_instance(exc, M.RedundantFlag) for c in 'dioxXeEfFgGcrsa%': yield t, ('%#' + c), (c in 'oxXeEfFgG') for flag in '0 +': yield t, ('%' + flag + c), (c in 'dioxXeEfFgG') yield t, ('%-' + c), True class test_width: def test_ok(self): def t(s): fmt = M.FormatString(s) assert_equal(len(fmt), 1) assert_sequence_equal(fmt.warnings, []) for c in 'dioxXeEfFgGcrsa%': yield t, ('%1' + c) def test_too_large(self): fmt = M.FormatString('%{0}d'.format(M.SSIZE_MAX)) assert_equal(len(fmt), 1) assert_equal(len(fmt.seq_arguments), 1) assert_equal(len(fmt.map_arguments), 0) with assert_raises(M.WidthRangeError): M.FormatString('%{0}d'.format(M.SSIZE_MAX + 1)) def test_variable(self): fmt = M.FormatString('%*s') assert_equal(len(fmt), 1) assert_equal(len(fmt.map_arguments), 0) [a1, a2] = fmt.seq_arguments assert_equal(a1.type, 'int') assert_equal(a2.type, 'str') def test_indexing_mixture(self): def t(s): with assert_raises(M.ArgumentIndexingMixture): M.FormatString(s) t('%*s%(eggs)s') t('%(eggs)s%*s') class test_precision: def test_ok(self): def t(s): fmt = M.FormatString(s) assert_equal(len(fmt), 1) for c in 'dioxXeEfFgGrsa': yield t, ('%.1' + c) def test_redundant_0(self): def t(s): fmt = M.FormatString(s) assert_equal(len(fmt), 1) [warning] = fmt.warnings assert_is_instance(warning, M.RedundantFlag) for c in 'dioxX': yield t, ('%0.1' + c) def test_non_redundant_0(self): def t(s): fmt = M.FormatString(s) assert_equal(len(fmt), 1) assert_sequence_equal(fmt.warnings, []) for c in 'eEfFgG': yield t, ('%0.1' + c) def test_unexpected(self): def t(s): fmt = M.FormatString(s) assert_equal(len(fmt), 1) [warning] = fmt.warnings assert_is_instance(warning, M.RedundantPrecision) for c in 'c%': yield t, ('%.1' + c) def test_too_large(self): fmt = M.FormatString('%.{0}f'.format(M.SSIZE_MAX)) assert_equal(len(fmt), 1) with assert_raises(M.PrecisionRangeError): M.FormatString('%.{0}f'.format(M.SSIZE_MAX + 1)) def test_variable(self): fmt = M.FormatString('%.*f') assert_equal(len(fmt), 1) assert_equal(len(fmt.map_arguments), 0) [a1, a2] = fmt.seq_arguments assert_equal(a1.type, 'int') assert_equal(a2.type, 'float') def test_indexing_mixture(self): def t(s): with assert_raises(M.ArgumentIndexingMixture): M.FormatString(s) t('%.*f%(eggs)f') t('%(eggs)f%.*f') class test_type_compatibility: def test_okay(self): def t(s, tp): fmt = M.FormatString(s) assert_equal(len(fmt.seq_arguments), 0) [args] = fmt.map_arguments.values() assert_greater(len(args), 1) for arg in args: assert_equal(arg.type, tp) t('%(eggs)d%(eggs)d', 'int') t('%(eggs)d%(eggs)i', 'int') def test_mismatch(self): def t(s): with assert_raises(M.ArgumentTypeMismatch): M.FormatString(s) t('%(eggs)d%(eggs)s') def test_seq_conversions(): def t(s, n): fmt = M.FormatString(s) assert_equal(len(fmt.seq_conversions), n) for arg in fmt.seq_conversions: assert_is_instance(arg, M.Conversion) t('%d', 1) t('%d%d', 2) t('eggs%dham', 1) t('%(eggs)d', 0) t('%*d', 1) t('%.*d', 1) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/test_tags.py0000644000000000000000000001053713733665553017355 0ustar00rootroot00000000000000# Copyright © 2012-2019 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 importlib import inspect import operator import pkgutil from nose.tools import ( assert_equal, assert_false, assert_is_instance, assert_raises, assert_true, ) import lib.check import lib.tags as M class test_escape: def t(self, s, expected): result = M.safe_format('{}', s) assert_is_instance(result, M.safestr) assert_equal( result, 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)) def ast_to_tagnames(node): for child in ast.iter_child_nodes(node): for t in ast_to_tagnames(child): yield t ok = ( 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) ) if ok: yield node.args[0].s def test_consistency(): source_tagnames = set() def visit_mod(modname): module = importlib.import_module(modname) source_path = inspect.getsourcefile(module) with open(source_path, 'rt', encoding='UTF-8') as file: source = file.read() node = ast.parse(source, filename=source_path) source_tagnames.update(ast_to_tagnames(node)) visit_mod('lib.check') for _, modname, _ in pkgutil.walk_packages(lib.check.__path__, 'lib.check.'): visit_mod(modname) tagnames = frozenset(tag.name for tag in M.iter_tags()) def test(tag): if tag not in source_tagnames: raise AssertionError('tag never emitted: ' + tag) if tag not in tagnames: raise AssertionError( 'tag missing in data/tags:\n\n' '[{tag}]\n' 'severity = wishlist\n' 'certainty = wild-guess\n' 'description = TODO'.format(tag=tag) ) for tag in sorted(source_tagnames | tagnames): yield test, tag class test_enums: def t(self, group, *keys): keys = [group[k] for k in keys] operators = ( operator.lt, operator.le, operator.eq, operator.ge, operator.gt, operator.ne, ) for op in operators: for i, x in enumerate(keys): for j, y in enumerate(keys): assert_equal(op(x, y), op(i, j)) if op is operator.eq: assert_false(op(x, j)) elif op is operator.ne: assert_true(op(x, j)) else: with assert_raises(TypeError): op(x, j) def test_severities(self): self.t(M.severities, 'pedantic', 'wishlist', 'minor', 'normal', 'important', 'serious', ) def test_certainties(self): self.t(M.certainties, 'wild-guess', 'possible', 'certain', ) # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/test_terminal.py0000644000000000000000000000633513733665553020233 0ustar00rootroot00000000000000# Copyright © 2012-2018 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 functools import os import pty import sys from nose.tools import ( assert_equal, ) import lib.terminal as T from . import tools def test_strip_delay(): def t(s, r=b''): assert_equal(T._strip_delay(s), r) # pylint: disable=protected-access 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 assert_tseq_equal(s, expected): class S(str): # assert_equal() does detailed comparison for instances of str, # but not their subclasses. We don't want detailed comparisons, # because diff could contain control characters. pass assert_equal(S(expected), S(s)) def test_dummy(): t = assert_tseq_equal for i in _get_colors(): t(T.attr_fg(i), '') t(T.attr_reset(), '') def pty_fork_isolation(term): def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): (master_fd, slave_fd) = pty.openpty() os.dup2(slave_fd, pty.STDOUT_FILENO) os.close(slave_fd) sys.stdout = sys.__stdout__ os.environ['TERM'] = term T.initialize() try: return func(*args, **kwargs) finally: os.close(master_fd) return tools.fork_isolation(wrapper) return decorator @pty_fork_isolation('vt100') def test_vt100(): t = assert_tseq_equal for i in _get_colors(): t(T.attr_fg(i), '') t(T.attr_reset(), '\x1B[m\x0F') @pty_fork_isolation('ansi') def test_ansi(): t = assert_tseq_equal t(T.attr_fg(T.colors.black), '\x1B[30m') t(T.attr_fg(T.colors.red), '\x1B[31m') t(T.attr_fg(T.colors.green), '\x1B[32m') t(T.attr_fg(T.colors.yellow), '\x1B[33m') t(T.attr_fg(T.colors.blue), '\x1B[34m') t(T.attr_fg(T.colors.magenta), '\x1B[35m') t(T.attr_fg(T.colors.cyan), '\x1B[36m') t(T.attr_fg(T.colors.white), '\x1B[37m') t(T.attr_reset(), '\x1B[0;10m') # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/test_version.py0000644000000000000000000000356313733665553020105 0ustar00rootroot00000000000000# Copyright © 2012-2018 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, 'manpage.rst') 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 sts=4 sw=4 et i18nspector-0.26/tests/test_xml.py0000644000000000000000000000505213733665553017213 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. import re import xml.etree.ElementTree as etree from nose.tools import ( assert_is_none, assert_is_not_none, assert_raises, ) import lib.xml as M class test_well_formed: def t(self, s): M.check_fragment(s) def test_ok(self): self.t('eggs') self.t('ham spam') def test_unknown_entity(self): self.t('&eggs;') class test_malformed: def t(self, s): with assert_raises(M.SyntaxError): M.check_fragment(s) def test_non_xml_character(self): self.t('\x01') def test_open_tag(self): self.t('ham') def test_closed_tag(self): self.t('eggs') def test_broken_entity(self): self.t('&#eggs;') def test_entity_def(self): s = ( ']>' '&eggs;' ) etree.fromstring(s) self.t(s) class test_name_re(): regexp = re.compile(r'\A{re}\Z'.format(re=M.name_re)) def test_good(self): def t(s): match = self.regexp.match(s) assert_is_not_none(match) t(':') t('_') t('e') t('e0') t('eggs') t('eggs-ham') t('eggs:ham') def test_bad(self): def t(s): match = self.regexp.match(s) assert_is_none(match) t('') t('0') t('-') t('e\N{GREEK QUESTION MARK}') # vim:ts=4 sts=4 sw=4 et i18nspector-0.26/tests/tools.py0000644000000000000000000000726013733665553016517 0ustar00rootroot00000000000000# Copyright © 2012-2019 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 functools import os import sys import tempfile import traceback import nose temporary_file = functools.partial( tempfile.NamedTemporaryFile, prefix='i18nspector.tests.', ) temporary_directory = functools.partial( tempfile.TemporaryDirectory, prefix='i18nspector.tests.', ) class IsolatedException(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 # pylint: disable=redefined-builtin,protected-access # sys.exit() can't be used here, because nose catches all exceptions, # including SystemExit # pylint:disable=consider-using-sys-exit @functools.wraps(f) def wrapper(*args, **kwargs): readfd, writefd = os.pipe() pid = os.fork() if pid == 0: # child: 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: # pylint: disable=broad-except 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: # parent: 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 IsolatedException() from Exception('\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)) # pylint:enable=consider-using-sys-exit 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 sts=4 sw=4 et