1from pytest import mark
2
3from translate.filters import checks, spelling
4from translate.lang import data
5from translate.storage import po, xliff
6
7
8def strprep(str1, str2, message=None):
9    return (
10        data.normalize(str1),
11        data.normalize(str2),
12        data.normalize(message),
13    )
14
15
16def check_category(filterfunction):
17    """Checks whether ``filterfunction`` has defined a category or not."""
18    return filterfunction.__name__ in filterfunction.__self__.categories
19
20
21def passes(filterfunction, str1, str2):
22    """returns whether the given strings pass on the given test, handling FilterFailures"""
23    str1, str2, no_message = strprep(str1, str2)
24    try:
25        filterresult = filterfunction(str1, str2)
26    except checks.FilterFailure:
27        filterresult = False
28
29    filterresult = filterresult and check_category(filterfunction)
30
31    return filterresult
32
33
34def fails(filterfunction, str1, str2, message=None):
35    """returns whether the given strings fail on the given test, handling only FilterFailures"""
36    str1, str2, message = strprep(str1, str2, message)
37    try:
38        filterresult = filterfunction(str1, str2)
39    except checks.SeriousFilterFailure:
40        filterresult = True
41    except checks.FilterFailure as e:
42        if message:
43            exc_message = e.messages[0]
44            filterresult = exc_message != message
45            print(exc_message.encode("utf-8"))
46        else:
47            filterresult = False
48
49    filterresult = filterresult and check_category(filterfunction)
50
51    return not filterresult
52
53
54def fails_serious(filterfunction, str1, str2, message=None):
55    """returns whether the given strings fail on the given test, handling only SeriousFilterFailures"""
56    str1, str2, message = strprep(str1, str2, message)
57    try:
58        filterresult = filterfunction(str1, str2)
59    except checks.SeriousFilterFailure as e:
60        if message:
61            exc_message = e.messages[0]
62            filterresult = exc_message != message
63            print(exc_message.encode("utf-8"))
64        else:
65            filterresult = False
66
67    filterresult = filterresult and check_category(filterfunction)
68
69    return not filterresult
70
71
72def test_defaults():
73    """tests default setup and that checks aren't altered by other constructions"""
74    stdchecker = checks.StandardChecker()
75    assert stdchecker.config.varmatches == []
76    mozillachecker = checks.MozillaChecker()
77    assert len(mozillachecker.config.varmatches) == 9
78    stdchecker = checks.StandardChecker()
79    assert stdchecker.config.varmatches == []
80
81
82def test_construct():
83    """tests that the checkers can be constructed"""
84    checks.StandardChecker()
85    checks.MozillaChecker()
86    checks.OpenOfficeChecker()
87    checks.LibreOfficeChecker()
88    checks.GnomeChecker()
89    checks.KdeChecker()
90    checks.IOSChecker()
91
92
93def test_accelerator_markers():
94    """test that we have the correct accelerator marker for the various default configs"""
95    stdchecker = checks.StandardChecker()
96    assert stdchecker.config.accelmarkers == []
97    mozillachecker = checks.MozillaChecker()
98    assert mozillachecker.config.accelmarkers == ["&"]
99    ooochecker = checks.OpenOfficeChecker()
100    assert ooochecker.config.accelmarkers == ["~"]
101    lochecker = checks.LibreOfficeChecker()
102    assert lochecker.config.accelmarkers == ["~"]
103    gnomechecker = checks.GnomeChecker()
104    assert gnomechecker.config.accelmarkers == ["_"]
105    kdechecker = checks.KdeChecker()
106    assert kdechecker.config.accelmarkers == ["&"]
107
108
109def test_messages():
110    """test that our helpers can check for messages and that these error messages can contain Unicode"""
111    stdchecker = checks.StandardChecker(
112        checks.CheckerConfig(
113            validchars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
114        )
115    )
116    assert fails(
117        stdchecker.validchars,
118        "Some unexpected characters",
119        "©",
120        "Invalid characters: '©' (\\u00a9)",
121    )
122    stdchecker = checks.StandardChecker()
123    assert fails_serious(
124        stdchecker.escapes,
125        r"A tab",
126        r"'n Ṱab\t",
127        r"""Escapes in original () don't match escapes in translation ('Ṱab\t')""",
128    )
129
130
131def test_accelerators():
132    """tests accelerators"""
133    stdchecker = checks.StandardChecker(checks.CheckerConfig(accelmarkers="&"))
134    assert passes(stdchecker.accelerators, "&File", "&Fayile")
135    assert fails(stdchecker.accelerators, "&File", "Fayile")
136    assert fails(stdchecker.accelerators, "File", "&Fayile")
137    assert passes(stdchecker.accelerators, "Mail && News", "Pos en Nuus")
138    assert fails(stdchecker.accelerators, "Mail & News", "Pos en Nuus")
139    assert passes(stdchecker.accelerators, "&Allow", "&\ufeb2\ufee3\ufe8e\ufea3")
140    assert fails(stdchecker.accelerators, "Open &File", "Vula& Ifayile")
141    kdechecker = checks.KdeChecker()
142    assert passes(kdechecker.accelerators, "&File", "&Fayile")
143    assert fails(kdechecker.accelerators, "&File", "Fayile")
144    assert fails(kdechecker.accelerators, "File", "&Fayile")
145    gnomechecker = checks.GnomeChecker()
146    assert passes(gnomechecker.accelerators, "_File", "_Fayile")
147    assert fails(gnomechecker.accelerators, "_File", "Fayile")
148    assert fails(gnomechecker.accelerators, "File", "_Fayile")
149    assert fails(gnomechecker.accelerators, "_File", "_Fayil_e")
150    mozillachecker = checks.MozillaChecker()
151    assert passes(mozillachecker.accelerators, "&File", "&Fayile")
152    assert passes(
153        mozillachecker.accelerators,
154        "Warn me if this will disable any of my add&-ons",
155        "&Waarsku my as dit enige van my byvoegings sal deaktiveer",
156    )
157    assert fails_serious(mozillachecker.accelerators, "&File", "Fayile")
158    assert fails_serious(mozillachecker.accelerators, "File", "&Fayile")
159    assert passes(mozillachecker.accelerators, "Mail & News", "Pos en Nuus")
160    assert fails_serious(mozillachecker.accelerators, "Mail & News", "Pos en &Nuus")
161    assert passes(mozillachecker.accelerators, "Mail & News", "Pos & Nuus")
162    ooochecker = checks.OpenOfficeChecker()
163    assert passes(ooochecker.accelerators, "~File", "~Fayile")
164    assert fails(ooochecker.accelerators, "~File", "Fayile")
165    assert fails(ooochecker.accelerators, "File", "~Fayile")
166
167    # We don't want an accelerator for letters with a diacritic
168    assert fails(ooochecker.accelerators, "F~ile", "L~êer")
169    lochecker = checks.LibreOfficeChecker()
170    assert passes(lochecker.accelerators, "~File", "~Fayile")
171    assert fails(lochecker.accelerators, "~File", "Fayile")
172    assert fails(lochecker.accelerators, "File", "~Fayile")
173
174    # We don't want an accelerator for letters with a diacritic
175    assert fails(lochecker.accelerators, "F~ile", "L~êer")
176
177    # Bug 289: accept accented accelerator characters
178    afchecker = checks.StandardChecker(
179        checks.CheckerConfig(accelmarkers="&", targetlanguage="fi")
180    )
181    assert passes(afchecker.accelerators, "&Reload Frame", "P&äivitä kehys")
182
183    trchecker = checks.StandardChecker(
184        checks.CheckerConfig(accelmarkers="&", targetlanguage="tr")
185    )
186    assert passes(trchecker.accelerators, "&Download", "&İndir")
187    assert passes(trchecker.accelerators, "&Business", "İ&ş")
188    assert passes(trchecker.accelerators, "&Remove", "Kald&ır")
189    assert passes(trchecker.accelerators, "&Three", "&Üç")
190    assert passes(trchecker.accelerators, "&Three", "Ü&ç")
191    assert passes(trchecker.accelerators, "&Before", "&Önce")
192    assert passes(trchecker.accelerators, "Fo&ur", "D&ört")
193    assert passes(trchecker.accelerators, "Mo&dern", "Ça&ğdaş")
194    assert passes(trchecker.accelerators, "Mo&dern", "&Çağdaş")
195    assert passes(trchecker.accelerators, "&February", "&Şubat")
196    assert passes(trchecker.accelerators, "P&lain", "D&üz")
197    assert passes(trchecker.accelerators, "GAR&DEN", "BA&Ğ")
198
199    # Problems:
200    # Accelerator before variable - see test_acceleratedvariables
201
202
203@mark.xfail(reason="Accelerated variables needs a better implementation")
204def test_acceleratedvariables():
205    """test for accelerated variables"""
206    # FIXME: disabled since acceleratedvariables has been removed, but these checks are still needed
207    mozillachecker = checks.MozillaChecker()
208    assert fails(mozillachecker.acceleratedvariables, "%S &Options", "&%S Ikhetho")
209    assert passes(mozillachecker.acceleratedvariables, "%S &Options", "%S &Ikhetho")
210    ooochecker = checks.OpenOfficeChecker()
211    assert fails(
212        ooochecker.acceleratedvariables,
213        "%PRODUCTNAME% ~Options",
214        "~%PRODUCTNAME% Ikhetho",
215    )
216    assert passes(
217        ooochecker.acceleratedvariables,
218        "%PRODUCTNAME% ~Options",
219        "%PRODUCTNAME% ~Ikhetho",
220    )
221    lochecker = checks.LibreOfficeChecker()
222    assert fails(
223        lochecker.acceleratedvariables,
224        "%PRODUCTNAME% ~Options",
225        "~%PRODUCTNAME% Ikhetho",
226    )
227    assert passes(
228        lochecker.acceleratedvariables,
229        "%PRODUCTNAME% ~Options",
230        "%PRODUCTNAME% ~Ikhetho",
231    )
232
233
234def test_acronyms():
235    """tests acronyms"""
236    stdchecker = checks.StandardChecker()
237    assert passes(stdchecker.acronyms, "An HTML file", "'n HTML leer")
238    assert fails(stdchecker.acronyms, "An HTML file", "'n LMTH leer")
239    assert passes(stdchecker.acronyms, "It is HTML.", "Dit is HTML.")
240    # We don't mind if you add an acronym to correct bad capitalisation in the original
241    assert passes(stdchecker.acronyms, "An html file", "'n HTML leer")
242    # We shouldn't worry about acronyms that appear in a musttranslate file
243    stdchecker = checks.StandardChecker(checks.CheckerConfig(musttranslatewords=["OK"]))
244    assert passes(stdchecker.acronyms, "OK", "Kulungile")
245    # Assert punctuation should not hide accronyms
246    assert fails(stdchecker.acronyms, "Location (URL) not found", "Blah blah blah")
247    # Test '-W' (bug 283)
248    assert passes(
249        stdchecker.acronyms,
250        "%s: option `-W %s' is ambiguous",
251        "%s: opsie '-W %s' is dubbelsinnig",
252    )
253
254
255def test_blank():
256    """tests blank"""
257    stdchecker = checks.StandardChecker()
258    assert fails(stdchecker.blank, "Save as", " ")
259    assert fails(stdchecker.blank, "_: KDE comment\\n\nSimple string", "  ")
260
261
262def test_brackets():
263    """tests brackets"""
264    stdchecker = checks.StandardChecker()
265    assert passes(stdchecker.brackets, "N number(s)", "N getal(le)")
266    assert fails(stdchecker.brackets, "For {sic} numbers", "Vier getalle")
267    assert fails(stdchecker.brackets, "For }sic{ numbers", "Vier getalle")
268    assert fails(stdchecker.brackets, "For [sic] numbers", "Vier getalle")
269    assert fails(stdchecker.brackets, "For ]sic[ numbers", "Vier getalle")
270    assert passes(stdchecker.brackets, "{[(", "[({")
271
272
273def test_compendiumconflicts():
274    """tests compendiumconflicts"""
275    stdchecker = checks.StandardChecker()
276    assert fails(
277        stdchecker.compendiumconflicts,
278        "File not saved",
279        r"""#-#-#-#-# file1.po #-#-#-#-#\n
280Leer nie gestoor gestoor nie\n
281#-#-#-#-# file1.po #-#-#-#-#\n
282Leer nie gestoor""",
283    )
284
285
286def test_doublequoting():
287    """tests double quotes"""
288    stdchecker = checks.StandardChecker()
289    assert fails(stdchecker.doublequoting, "Hot plate", '"Ipuleti" elishisa')
290    assert passes(stdchecker.doublequoting, '"Hot" plate', '"Ipuleti" elishisa')
291    assert fails(stdchecker.doublequoting, "'Hot' plate", '"Ipuleti" elishisa')
292    assert passes(stdchecker.doublequoting, '\\"Hot\\" plate', '\\"Ipuleti\\" elishisa')
293
294    # We don't want the filter to complain about "untranslated" quotes in xml attributes
295    frchecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="fr"))
296    assert passes(
297        frchecker.doublequoting,
298        'Click <a href="page.html">',
299        'Clique <a href="page.html">',
300    )
301    assert fails(frchecker.doublequoting, 'Do "this"', 'Do "this"')
302    assert passes(frchecker.doublequoting, 'Do "this"', "Do « this »")
303    assert fails(frchecker.doublequoting, 'Do "this"', "Do « this » « this »")
304    # This used to fail because we strip variables, and was left with an empty quotation that was not converted
305    assert passes(
306        frchecker.doublequoting, "Copying `%s' to `%s'", "Copie de « %s » vers « %s »"
307    )
308
309    vichecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="vi"))
310    assert passes(vichecker.doublequoting, 'Save "File"', "Lưu « Tập tin »")
311
312    # Had a small exception with such a case:
313    eschecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="es"))
314    assert passes(
315        eschecker.doublequoting,
316        "<![CDATA[ Enter the name of the Windows workgroup that this server should appear in. ]]>",
317        "<![CDATA[ Ingrese el nombre del grupo de trabajo de Windows en el que debe aparecer este servidor. ]]>",
318    )
319
320
321def test_doublespacing():
322    """tests double spacing"""
323    stdchecker = checks.StandardChecker()
324    assert passes(
325        stdchecker.doublespacing, "Sentence.  Another sentence.", "Sin.  'n Ander sin."
326    )
327    assert passes(
328        stdchecker.doublespacing,
329        "Sentence. Another sentence.",
330        "Sin. No double spacing.",
331    )
332    assert fails(
333        stdchecker.doublespacing,
334        "Sentence.  Another sentence.",
335        "Sin. Missing the double space.",
336    )
337    assert fails(
338        stdchecker.doublespacing,
339        "Sentence. Another sentence.",
340        "Sin.  Uneeded double space in translation.",
341    )
342    ooochecker = checks.OpenOfficeChecker()
343    assert passes(
344        ooochecker.doublespacing, "Execute %PROGRAMNAME Calc", "Blah %PROGRAMNAME Calc"
345    )
346    assert passes(
347        ooochecker.doublespacing, "Execute %PROGRAMNAME Calc", "Blah % PROGRAMNAME Calc"
348    )
349    lochecker = checks.LibreOfficeChecker()
350    assert passes(
351        lochecker.doublespacing, "Execute %PROGRAMNAME Calc", "Blah %PROGRAMNAME Calc"
352    )
353    assert passes(
354        lochecker.doublespacing, "Execute %PROGRAMNAME Calc", "Blah % PROGRAMNAME Calc"
355    )
356
357
358def test_doublewords():
359    """tests doublewords"""
360    stdchecker = checks.StandardChecker()
361    assert passes(stdchecker.doublewords, "Save the rhino", "Save the rhino")
362    assert fails(stdchecker.doublewords, "Save the rhino", "Save the the rhino")
363    # Double variables are not an error
364    stdchecker = checks.StandardChecker(checks.CheckerConfig(varmatches=[("%", 1)]))
365    assert passes(stdchecker.doublewords, "%s %s installation", "tsenyo ya %s %s")
366    # Double XML tags are not an error
367    stdchecker = checks.StandardChecker()
368    assert passes(
369        stdchecker.doublewords,
370        "Line one <br> <br> line two",
371        "Lyn een <br> <br> lyn twee",
372    )
373    # In some language certain double words are not errors
374    st_checker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="st"))
375    assert passes(
376        st_checker.doublewords,
377        "Color to draw the name of a message you sent.",
378        "Mmala wa ho taka bitso la molaetsa oo o o rometseng.",
379    )
380    assert passes(st_checker.doublewords, "Ten men", "Banna ba ba leshome")
381    assert passes(st_checker.doublewords, "Give SARS the tax", "Lekgetho le le fe SARS")
382
383
384def test_endpunc():
385    """tests endpunc"""
386    stdchecker = checks.StandardChecker()
387    assert passes(stdchecker.endpunc, "Question?", "Correct?")
388    assert fails(stdchecker.endpunc, " Question?", "Wrong ?")
389    # Newlines must not mask end punctuation
390    assert fails(
391        stdchecker.endpunc,
392        "Exit change recording mode?\n\n",
393        "Phuma esimeni sekugucula kubhalisa.\n\n",
394    )
395    mozillachecker = checks.MozillaChecker()
396    assert passes(
397        mozillachecker.endpunc,
398        "Upgrades an existing $ProductShortName$ installation.",
399        "Ku antswisiwa ka ku nghenisiwa ka $ProductShortName$.",
400    )
401    # Real examples
402    assert passes(
403        stdchecker.endpunc,
404        "A nickname that identifies this publishing site (e.g.: 'MySite')",
405        "Vito ro duvulela leri tirhisiwaka ku kuma sayiti leri ro kandziyisa (xik.: 'Sayiti ra Mina')",
406    )
407    assert fails(stdchecker.endpunc, "Question", "Wrong\u2026")
408    # Making sure singlequotes don't confuse things
409    assert passes(
410        stdchecker.endpunc,
411        "Pseudo-elements can't be negated '%1$S'.",
412        "Pseudo-elemente kan nie '%1$S' ontken word nie.",
413    )
414
415    stdchecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="km"))
416    assert passes(
417        stdchecker.endpunc,
418        "In this new version, there are some minor conversion improvements on complex style in Openoffice.org Writer.",
419        "នៅ​ក្នុង​កំណែ​ថ្មីនេះ មាន​ការ​កែសម្រួល​មួយ​ចំនួន​តូច​ទាក់​ទង​នឹង​ការ​បំលែង​ពុម្ពអក្សរ​ខ្មែរ​ ក្នុង​កម្មវិធី​ការិយាល័យ​ ស្លឹករឹត ដែល​មាន​ប្រើ​ប្រាស់​រចនាប័ទ្មស្មុគស្មាញច្រើន\u00a0។",
420    )
421
422    stdchecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="zh"))
423    assert passes(
424        stdchecker.endpunc,
425        "To activate your account, follow this link:\n",
426        "要啟用戶口,請瀏覽這個鏈結:\n",
427    )
428
429    stdchecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="vi"))
430    assert passes(
431        stdchecker.endpunc,
432        "Do you want to delete the XX dialog?",
433        "Bạn có muốn xoá hộp thoại XX không?",
434    )
435
436    stdchecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="fr"))
437    assert passes(stdchecker.endpunc, "Header:", "En-tête :")
438    assert passes(stdchecker.endpunc, "Header:", "En-tête\u00a0:")
439
440
441def test_endwhitespace():
442    """tests endwhitespace"""
443    stdchecker = checks.StandardChecker()
444    assert passes(stdchecker.endwhitespace, "A setence.", "I'm correct.")
445    assert passes(stdchecker.endwhitespace, "A setence. ", "I'm correct. ")
446    assert fails(stdchecker.endwhitespace, "A setence. ", "'I'm incorrect.")
447    assert passes(
448        stdchecker.endwhitespace,
449        "Problem with something: %s\n",
450        "Probleem met iets: %s\n",
451    )
452
453    zh_checker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="zh"))
454    # This should pass since the space is not needed in Chinese
455    assert passes(zh_checker.endwhitespace, "Init. Limit: ", "起始时间限制:")
456
457
458def test_escapes():
459    """tests escapes"""
460    stdchecker = checks.StandardChecker()
461    assert passes(stdchecker.escapes, r"""A sentence""", "I'm correct.")
462    assert passes(stdchecker.escapes, "A file\n", "'n Leer\n")
463    assert fails_serious(stdchecker.escapes, r"blah. A file", r"bleah.\n'n leer")
464    assert passes(stdchecker.escapes, r"A tab\t", r"'n Tab\t")
465    assert fails_serious(stdchecker.escapes, r"A tab\t", r"'n Tab")
466    assert passes(stdchecker.escapes, r"An escape escape \\", r"Escape escape \\")
467    assert fails_serious(stdchecker.escapes, r"An escape escape \\", "Escape escape")
468    assert passes(stdchecker.escapes, r"A double quote \"", r"Double quote \"")
469    assert fails_serious(stdchecker.escapes, r"A double quote \"", "Double quote")
470    # Escaped escapes
471    assert passes(stdchecker.escapes, "An escaped newline \\n", "Escaped newline \\n")
472    assert fails_serious(
473        stdchecker.escapes, "An escaped newline \\n", "Escaped newline \n"
474    )
475    # Real example
476    ooochecker = checks.OpenOfficeChecker()
477    assert passes(
478        ooochecker.escapes,
479        ",\t44\t;\t59\t:\t58\t{Tab}\t9\t{space}\t32",
480        ",\t44\t;\t59\t:\t58\t{Tab}\t9\t{space}\t32",
481    )
482    lochecker = checks.LibreOfficeChecker()
483    assert passes(
484        lochecker.escapes,
485        ",\t44\t;\t59\t:\t58\t{Tab}\t9\t{space}\t32",
486        ",\t44\t;\t59\t:\t58\t{Tab}\t9\t{space}\t32",
487    )
488
489
490def test_newlines():
491    """tests newlines"""
492    stdchecker = checks.StandardChecker()
493    assert passes(stdchecker.newlines, "Nothing to see", "Niks te sien")
494    assert passes(stdchecker.newlines, "Correct\n", "Korrek\n")
495    assert passes(stdchecker.newlines, "Correct\r", "Korrek\r")
496    assert passes(stdchecker.newlines, "Correct\r\n", "Korrek\r\n")
497    assert fails(stdchecker.newlines, "A file\n", "'n Leer")
498    assert fails(stdchecker.newlines, "A file", "'n Leer\n")
499    assert fails(stdchecker.newlines, "A file\r", "'n Leer")
500    assert fails(stdchecker.newlines, "A file", "'n Leer\r")
501    assert fails(stdchecker.newlines, "A file\n", "'n Leer\r\n")
502    assert fails(stdchecker.newlines, "A file\r\n", "'n Leer\n")
503    assert fails(stdchecker.newlines, "blah.\nA file", "bleah. 'n leer")
504    # msgfmt errors
505    assert fails(stdchecker.newlines, "One two\n", "Een\ntwee")
506    assert fails(stdchecker.newlines, "\nOne two", "Een\ntwee")
507    # Real example
508    ooochecker = checks.OpenOfficeChecker()
509    assert fails(
510        ooochecker.newlines,
511        "The arrowhead was modified without saving.\nWould you like to save the arrowhead now?",
512        "Ṱhoho ya musevhe yo khwinifhadzwa hu si na u seiva.Ni khou ṱoda u seiva thoho ya musevhe zwino?",
513    )
514    lochecker = checks.LibreOfficeChecker()
515    assert fails(
516        lochecker.newlines,
517        "The arrowhead was modified without saving.\nWould you like to save the arrowhead now?",
518        "Ṱhoho ya musevhe yo khwinifhadzwa hu si na u seiva.Ni khou ṱoda u seiva thoho ya musevhe zwino?",
519    )
520
521
522def test_tabs():
523    """tests tabs"""
524    stdchecker = checks.StandardChecker()
525    assert passes(stdchecker.tabs, "Nothing to see", "Niks te sien")
526    assert passes(stdchecker.tabs, "Correct\t", "Korrek\t")
527    assert passes(stdchecker.tabs, "Correct\tAA", "Korrek\tAA")
528    assert fails_serious(stdchecker.tabs, "A file\t", "'n Leer")
529    assert fails_serious(stdchecker.tabs, "A file", "'n Leer\t")
530    ooochecker = checks.OpenOfficeChecker()
531    assert passes(
532        ooochecker.tabs,
533        ",\t44\t;\t59\t:\t58\t{Tab}\t9\t{space}\t32",
534        ",\t44\t;\t59\t:\t58\t{Tab}\t9\t{space}\t32",
535    )
536    lochecker = checks.LibreOfficeChecker()
537    assert passes(
538        lochecker.tabs,
539        ",\t44\t;\t59\t:\t58\t{Tab}\t9\t{space}\t32",
540        ",\t44\t;\t59\t:\t58\t{Tab}\t9\t{space}\t32",
541    )
542
543
544def test_filepaths():
545    """tests filepaths"""
546    stdchecker = checks.StandardChecker()
547    assert passes(
548        stdchecker.filepaths,
549        "%s to the file /etc/hosts on your system.",
550        "%s na die leer /etc/hosts op jou systeem.",
551    )
552    assert fails(
553        stdchecker.filepaths,
554        "%s to the file /etc/hosts on your system.",
555        "%s na die leer /etc/gasheer op jou systeem.",
556    )
557    assert passes(
558        stdchecker.filepaths, "Text with <br />line break", "Teks met <br /> lynbreuk"
559    )
560
561
562def test_kdecomments():
563    """tests kdecomments"""
564    stdchecker = checks.StandardChecker()
565    assert passes(
566        stdchecker.kdecomments,
567        r"""_: I am a comment\n
568A string to translate""",
569        "'n String om te vertaal",
570    )
571    assert fails(
572        stdchecker.kdecomments,
573        r"""_: I am a comment\n
574A string to translate""",
575        r"""_: Ek is 'n commment\n
576'n String om te vertaal""",
577    )
578    assert fails(
579        stdchecker.kdecomments,
580        """_: I am a comment\\n\n""",
581        """_: I am a comment\\n\n""",
582    )
583
584
585def test_long():
586    """tests long messages"""
587    stdchecker = checks.StandardChecker()
588    assert passes(stdchecker.long, "I am normal", "Ek is ook normaal")
589    assert fails(
590        stdchecker.long,
591        "Short.",
592        "Kort.......................................................................................",
593    )
594    assert fails(stdchecker.long, "a", "bc")
595
596
597@mark.xfail(reason="FIXME: All fails() tests are not working")
598def test_musttranslatewords():
599    """tests stopwords"""
600    stdchecker = checks.StandardChecker(checks.CheckerConfig(musttranslatewords=[]))
601    assert passes(
602        stdchecker.musttranslatewords,
603        "This uses Mozilla of course",
604        "hierdie gebruik le mozille natuurlik",
605    )
606    stdchecker = checks.StandardChecker(
607        checks.CheckerConfig(musttranslatewords=["Mozilla"])
608    )
609    assert passes(
610        stdchecker.musttranslatewords,
611        "This uses Mozilla of course",
612        "hierdie gebruik le mozille natuurlik",
613    )
614    assert fails(
615        stdchecker.musttranslatewords,
616        "This uses Mozilla of course",
617        "hierdie gebruik Mozilla natuurlik",
618    )
619    assert passes(
620        stdchecker.musttranslatewords,
621        "This uses Mozilla. Don't you?",
622        "hierdie gebruik le mozille soos jy",
623    )
624    assert fails(
625        stdchecker.musttranslatewords,
626        "This uses Mozilla. Don't you?",
627        "hierdie gebruik Mozilla soos jy",
628    )
629    # should always pass if there are no stopwords in the original
630    assert passes(
631        stdchecker.musttranslatewords,
632        "This uses something else. Don't you?",
633        "hierdie gebruik Mozilla soos jy",
634    )
635    # check that we can find words surrounded by punctuation
636    assert passes(
637        stdchecker.musttranslatewords,
638        "Click 'Mozilla' button",
639        "Kliek 'Motzille' knoppie",
640    )
641    assert fails(
642        stdchecker.musttranslatewords,
643        "Click 'Mozilla' button",
644        "Kliek 'Mozilla' knoppie",
645    )
646    assert passes(
647        stdchecker.musttranslatewords,
648        'Click "Mozilla" button',
649        'Kliek "Motzille" knoppie',
650    )
651    assert fails(
652        stdchecker.musttranslatewords,
653        'Click "Mozilla" button',
654        'Kliek "Mozilla" knoppie',
655    )
656    assert fails(
657        stdchecker.musttranslatewords,
658        'Click "Mozilla" button',
659        "Kliek «Mozilla» knoppie",
660    )
661    assert passes(
662        stdchecker.musttranslatewords,
663        "Click (Mozilla) button",
664        "Kliek (Motzille) knoppie",
665    )
666    assert fails(
667        stdchecker.musttranslatewords,
668        "Click (Mozilla) button",
669        "Kliek (Mozilla) knoppie",
670    )
671    assert passes(stdchecker.musttranslatewords, "Click Mozilla!", "Kliek Motzille!")
672    assert fails(stdchecker.musttranslatewords, "Click Mozilla!", "Kliek Mozilla!")
673    ## We need to define more word separators to allow us to find those hidden untranslated items
674    # assert fails(stdchecker.musttranslatewords, "Click OK", "Blah we-OK")
675    # Don't get confused when variables are the same as a musttranslate word
676    stdchecker = checks.StandardChecker(
677        checks.CheckerConfig(
678            varmatches=[
679                ("%", None),
680            ],
681            musttranslatewords=["OK"],
682        )
683    )
684    assert passes(
685        stdchecker.musttranslatewords, "Click %OK to start", "Kliek %OK om te begin"
686    )
687    # Unicode
688    assert fails(stdchecker.musttranslatewords, "Click OK", "Kiḽikani OK")
689
690
691def test_notranslatewords():
692    """tests stopwords"""
693    stdchecker = checks.StandardChecker(checks.CheckerConfig(notranslatewords=[]))
694    assert passes(
695        stdchecker.notranslatewords,
696        "This uses Mozilla of course",
697        "hierdie gebruik le mozille natuurlik",
698    )
699    stdchecker = checks.StandardChecker(
700        checks.CheckerConfig(notranslatewords=["Mozilla", "Opera"])
701    )
702    assert fails(
703        stdchecker.notranslatewords,
704        "This uses Mozilla of course",
705        "hierdie gebruik le mozille natuurlik",
706    )
707    assert passes(
708        stdchecker.notranslatewords,
709        "This uses Mozilla of course",
710        "hierdie gebruik Mozilla natuurlik",
711    )
712    assert fails(
713        stdchecker.notranslatewords,
714        "This uses Mozilla. Don't you?",
715        "hierdie gebruik le mozille soos jy",
716    )
717    assert passes(
718        stdchecker.notranslatewords,
719        "This uses Mozilla. Don't you?",
720        "hierdie gebruik Mozilla soos jy",
721    )
722    # should always pass if there are no stopwords in the original
723    assert passes(
724        stdchecker.notranslatewords,
725        "This uses something else. Don't you?",
726        "hierdie gebruik Mozilla soos jy",
727    )
728    # Cope with commas
729    assert passes(
730        stdchecker.notranslatewords,
731        "using Mozilla Task Manager",
732        "šomiša Selaola Mošomo sa Mozilla, gomme",
733    )
734    # Find words even if they are embedded in punctuation
735    assert fails(
736        stdchecker.notranslatewords,
737        "Click 'Mozilla' button",
738        "Kliek 'Motzille' knoppie",
739    )
740    assert passes(
741        stdchecker.notranslatewords, "Click 'Mozilla' button", "Kliek 'Mozilla' knoppie"
742    )
743    assert fails(stdchecker.notranslatewords, "Click Mozilla!", "Kliek Motzille!")
744    assert passes(stdchecker.notranslatewords, "Click Mozilla!", "Kliek Mozilla!")
745    assert fails(
746        stdchecker.notranslatewords,
747        "Searches (From Opera)",
748        "adosako (kusukela ku- Ophera)",
749    )
750    stdchecker = checks.StandardChecker(
751        checks.CheckerConfig(notranslatewords=["Sun", "NeXT"])
752    )
753    assert fails(
754        stdchecker.notranslatewords, "Sun/NeXT Audio", "Odio dza Ḓuvha/TeVHELAHO"
755    )
756    assert passes(stdchecker.notranslatewords, "Sun/NeXT Audio", "Odio dza Sun/NeXT")
757    stdchecker = checks.StandardChecker(
758        checks.CheckerConfig(notranslatewords=["sendmail"])
759    )
760    assert fails(
761        stdchecker.notranslatewords,
762        "because 'sendmail' could",
763        "ngauri 'rumelameiḽi' a yo",
764    )
765    assert passes(
766        stdchecker.notranslatewords,
767        "because 'sendmail' could",
768        "ngauri 'sendmail' a yo",
769    )
770    stdchecker = checks.StandardChecker(checks.CheckerConfig(notranslatewords=["Base"]))
771    assert fails(
772        stdchecker.notranslatewords,
773        " - %PRODUCTNAME Base: Relation design",
774        " - %PRODUCTNAME Sisekelo: Umsiko wekuhlobana",
775    )
776    stdchecker = checks.StandardChecker(
777        checks.CheckerConfig(notranslatewords=["Writer"])
778    )
779    assert fails(
780        stdchecker.notranslatewords,
781        "&[ProductName] Writer/Web",
782        "&[ProductName] Umbhali/iWebhu",
783    )
784    # Unicode - different decompositions
785    stdchecker = checks.StandardChecker(
786        checks.CheckerConfig(notranslatewords=["\u1e3cike"])
787    )
788    assert passes(
789        stdchecker.notranslatewords, "You \u1e3cike me", "Ek \u004c\u032dike jou"
790    )
791
792
793def test_numbers():
794    """test numbers"""
795    stdchecker = checks.StandardChecker()
796    assert passes(
797        stdchecker.numbers,
798        "Netscape 4 was not as good as Netscape 7.",
799        "Netscape 4 was nie so goed soos Netscape 7 nie.",
800    )
801    # Check for correct detection of degree.  Also check that we aren't getting confused with 1 and 2 byte UTF-8 characters
802    assert fails(stdchecker.numbers, "180° turn", "180 turn")
803    assert passes(stdchecker.numbers, "180° turn", "180° turn")
804    assert fails(stdchecker.numbers, "180° turn", "360 turn")
805    assert fails(stdchecker.numbers, "180° turn", "360° turn")
806    assert passes(stdchecker.numbers, "180~ turn", "180 turn")
807    assert passes(stdchecker.numbers, "180¶ turn", "180 turn")
808    # Numbers with multiple decimal points
809    assert passes(stdchecker.numbers, "12.34.56", "12.34.56")
810    assert fails(stdchecker.numbers, "12.34.56", "98.76.54")
811    # Currency
812    # FIXME we should probably be able to handle currency checking with locale inteligence
813    assert passes(stdchecker.numbers, "R57.60", "R57.60")
814    # FIXME - again locale intelligence should allow us to use other decimal seperators
815    assert fails(stdchecker.numbers, "R57.60", "R57,60")
816    assert fails(stdchecker.numbers, "1,000.00", "1 000,00")
817    # You should be able to reorder numbers
818    assert passes(
819        stdchecker.numbers,
820        "40-bit RC2 encryption with RSA and an MD5",
821        "Umbhalo ocashile i-RC2 onamabhithi angu-40 one-RSA ne-MD5",
822    )
823    # Don't fail the numbers check if the entry is a dialogsize entry
824    mozillachecker = checks.MozillaChecker()
825    assert passes(mozillachecker.numbers, "width: 12em;", "width: 20em;")
826
827
828def test_persian_numbers():
829    """test non latin numbers for Persian (RTL)"""
830    fa_checker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="fa"))
831    assert passes(fa_checker.numbers, "&حرکت آهسته (۰.۵×)", "&Slow Motion (0.5×)")
832    assert passes(fa_checker.numbers, "&حرکت آهسته (0.5×)", "&Slow Motion (0.5×)")
833    assert passes(
834        fa_checker.numbers, '<img alt="١۰" width="10" />', '<img alt="10" width="10" />'
835    )
836    assert passes(
837        fa_checker.numbers, '<img alt="10" width="10" />', '<img alt="10" width="10" />'
838    )
839    assert passes(
840        fa_checker.numbers, "دسترسی مسدود شده است (۴۰۳)", "Access denied (403)"
841    )
842    assert passes(fa_checker.numbers, "کتاب موزیلا، ۱۵:۱", "The Book of Mozilla, 15:1")
843    assert passes(
844        fa_checker.numbers,
845        "<p>نشانی درخواست مشخصا(به عنوان مثال<q>mozilla.org:80</q>برای درگاه ۸۰ بر روی  mozilla.org)  ازدرگاهی استفاده می کندکه در حالت عادی به عنوان کاربردی <em>به غیر</em> از وبگردی استفاده می شود.مرورگر برای حفاظت و امنیت شما این درخواست را لغوکرد.</p>",
846        "<p>The requested address specified a port (e.g. <q>mozilla.org:80</q> for port 80 on mozilla.org) normally used for purposes <em>other</em> than Web browsing. The browser has canceled the request for your protection and security.</p>",
847    )
848    assert passes(
849        fa_checker.numbers,
850        "دستور پردازشی <?%1$S?> دیگر تأثیری خارج از prolog ندارد (برای اطلاعات بیشتر، اشکال ۳۶۰۱۱۹ را مشاهده کنید).",
851        "<?%1$S?> processing instruction does not have any effect outside the prolog anymore (see bug 360119).",
852    )
853    assert passes(
854        fa_checker.numbers,
855        "encoding حروف این سند بسیار دیرتر از آنکه مورد اثر واقع شود شناسایی شد.encoding فایل برای شناسایی باید به ۱۰۲۴ بایت اول فایل برای شناسایی منتقل شود.",
856        "The character encoding declaration of document was found too late for it to take effect. The encoding declaration needs to be moved to be within the first 1024 bytes of the file.",
857    )
858    assert passes(
859        fa_checker.numbers,
860        "ویدئو یا صدا در این صفحه نرم‌افزار DRMای احتیاج دارد که نسخه ۶۴ بیتی از %1$S از آن پیشتیبانی نمی‌کند. %2$S",
861        "The audio or video on this page requires DRM software that this 64-bit build of %1$S does not support. %2$S",
862    )
863    assert passes(
864        fa_checker.numbers,
865        "شما اندازه خیلی بزرگی برای حداقل اندازه قلم انتخاب کرده‌اید (بیش از ۲۴ پیکسل). این ممکن است باعث شود پیکربندی صفحاتی مانند این سخت یا غیرممکن بشود.",
866        "You have selected a very large minimum font size (more than 24 pixels). This may make it difficult or impossible to use some important configuration pages like this one.",
867    )
868
869
870def test_bengali_numbers():
871    """test non latin numbers for Bengali (LTR)"""
872    bn_checker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="bn"))
873    assert passes(bn_checker.numbers, "উচ্চ গতি (১.৫ গুন)", "&High Speed (1.5×)")
874    assert passes(bn_checker.numbers, "উচ্চ গতি (0.5 গুন)", "&Slow Motion (0.5×)")
875    assert passes(
876        bn_checker.numbers, '<img alt="১০" width="10" />', '<img alt="10" width="10" />'
877    )
878    assert passes(
879        bn_checker.numbers, '<img alt="10" width="10" />', '<img alt="10" width="10" />'
880    )
881    assert passes(
882        bn_checker.numbers,
883        "<strong>Mozilla-র বই</strong>১৫: ১ পাতা থেকে সংগৃহীত",
884        "from <strong>The Book of Mozilla,</strong> 15:1",
885    )
886    assert passes(
887        bn_checker.numbers,
888        "ট্যাগ গুলি ২৫ টি অক্ষরের মধ্যে সীমাবদ্ধ",
889        "Tags are limited to 25 characters",
890    )
891    assert passes(
892        bn_checker.numbers,
893        "পাসওয়ার্ড অন্তত ৮-টি অক্ষর বিশিষ্ট হওয়া আবশ্যক এবং এই ক্ষেত্রে ব্যবহারকারী অ্যাকাউন্টের নাম অথবা পুনরুদ্ধারের (key) পাসওয়ার্ড রূপে ব্যবহার করা যাবে না।",
894        "Your password must be at least 8 characters long.  It cannot be the same as either your user name or your Recovery Key.",
895    )
896
897
898def test_arabic_numbers():
899    """test non latin numbers for Arabic"""
900    ar_checker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="ar"))
901    assert passes(
902        ar_checker.numbers,
903        "أقصى طول للوسم ٢٥ حرفًا",
904        "Tags are limited to 25 characters",
905    )
906    assert passes(ar_checker.numbers, "حركة ب&طيئة (٠٫٥×)", "&Slow Motion (0.5×)")
907    assert passes(ar_checker.numbers, "متصفح &٣٦٠ الآمن", "&360 Secure Browser")
908    assert passes(
909        ar_checker.numbers,
910        "من <strong>كتاب موزيلا،</strong> ١٥‏:١",
911        "from <strong>The Book of Mozilla,</strong> 15:1",
912    )
913    assert passes(ar_checker.numbers, "١٧٥٪", "175%")
914
915
916def test_assamese_numbers():
917    """test non latin numbers for Assamese"""
918    as_checker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="as"))
919    assert passes(
920        as_checker.numbers,
921        "প্ৰতি ৩ ছেকেণ্ডত স্বচালিতভাৱে সতেজ কৰক",
922        "Autorefresh every 3 seconds",
923    )
924    assert passes(
925        as_checker.numbers,
926        "পৃষ্ঠা পুনৰ ল'ড কৰা হৈছিল, কাৰণ HTML দস্তাবেজৰ আখৰ এনক'ডিং যোষণা ফাইলৰ প্ৰথম ১০২৪ বাইট পূৰ্বস্কেন কৰোতে পোৱা নগল। এনক'ডিং ঘোষণাক ফাইলৰ প্ৰথম ১০২৪ বাইটৰ মাজত স্থানান্তৰ কৰিব লাগিব।",
927        "The page was reloaded, because the character encoding declaration of the HTML document was not found when prescanning the first 1024 bytes of the file. The encoding declaration needs to be moved to be within the first 1024 bytes of the file.",
928    )
929    assert passes(as_checker.numbers, "সংস্কৰণ ৩", "Version 3")
930    assert passes(as_checker.numbers, "১৭৫%", "175%")
931
932
933def test_options():
934    """tests command line options e.g. --option"""
935    stdchecker = checks.StandardChecker()
936    assert passes(stdchecker.options, "--help", "--help")
937    assert fails(stdchecker.options, "--help", "--hulp")
938    assert fails(stdchecker.options, "--input=FILE", "--input=FILE")
939    assert passes(stdchecker.options, "--input=FILE", "--input=LÊER")
940    assert fails(stdchecker.options, "--input=FILE", "--tovoer=LÊER")
941    # We don't want just any '--' to trigger this test - the error will be confusing
942    assert passes(stdchecker.options, "Hello! -- Hi", "Hallo! &mdash; Haai")
943    assert passes(stdchecker.options, "--blank--", "--vide--")
944
945
946def test_printf():
947    """tests printf style variables"""
948    # This should really be a subset of the variable checks
949    # Ideally we should be able to adapt based on #, directives also
950    stdchecker = checks.StandardChecker()
951    assert passes(stdchecker.printf, "I am %s", "Ek is %s")
952    assert fails(stdchecker.printf, "I am %s", "Ek is %d")
953    assert passes(stdchecker.printf, "I am %#100.50hhf", "Ek is %#100.50hhf")
954    assert fails(stdchecker.printf, "I am %#100s", "Ek is %10s")
955    assert fails(
956        stdchecker.printf,
957        "... for user %.100s on %.100s:",
958        "... lomuntu osebenzisa i-%. I-100s e-100s:",
959    )
960    assert passes(stdchecker.printf, "%dMB", "%d MG")
961    # Reordering
962    assert passes(
963        stdchecker.printf, "String %s and number %d", "String %1$s en nommer %2$d"
964    )
965    assert passes(
966        stdchecker.printf, "String %1$s and number %2$d", "String %1$s en nommer %2$d"
967    )
968    assert passes(
969        stdchecker.printf, "String %s and number %d", "Nommer %2$d and string %1$s"
970    )
971    assert passes(
972        stdchecker.printf,
973        "String %s and real number %f and number %d",
974        "String %1$s en nommer %3$d en reële getal %2$f",
975    )
976    assert passes(
977        stdchecker.printf,
978        "String %1$s and real number %2$f and number %3$d",
979        "String %1$s en nommer %3$d en reële getal %2$f",
980    )
981    assert passes(
982        stdchecker.printf,
983        "Real number %2$f and string %1$s and number %3$d",
984        "String %1$s en nommer %3$d en reële getal %2$f",
985    )
986    assert fails(
987        stdchecker.printf, "String %s and number %d", "Nommer %1$d and string %2$s"
988    )
989    assert fails(
990        stdchecker.printf,
991        "String %s and real number %f and number %d",
992        "String %1$s en nommer %3$d en reële getal %2$d",
993    )
994    assert fails(
995        stdchecker.printf,
996        "String %s and real number %f and number %d",
997        "String %1$s en nommer %3$d en reële getal %4$f",
998    )
999    assert fails(
1000        stdchecker.printf,
1001        "String %s and real number %f and number %d",
1002        "String %2$s en nommer %3$d en reële getal %2$f",
1003    )
1004    assert fails(
1005        stdchecker.printf,
1006        "Real number %2$f and string %1$s and number %3$d",
1007        "String %1$f en nommer %3$d en reële getal %2$f",
1008    )
1009    # checking python format strings
1010    assert passes(
1011        stdchecker.printf,
1012        "String %(1)s and number %(2)d",
1013        "Nommer %(2)d en string %(1)s",
1014    )
1015    assert passes(
1016        stdchecker.printf,
1017        "String %(str)s and number %(num)d",
1018        "Nommer %(num)d en string %(str)s",
1019    )
1020    assert fails(
1021        stdchecker.printf,
1022        "String %(str)s and number %(num)d",
1023        "Nommer %(nommer)d en string %(str)s",
1024    )
1025    assert fails(
1026        stdchecker.printf,
1027        "String %(str)s and number %(num)d",
1028        "Nommer %(num)d en string %s",
1029    )
1030    # checking omitted plural format string placeholder %.0s
1031    stdchecker.hasplural = 1
1032    assert passes(stdchecker.printf, "%d plurals", "%.0s plural")
1033    # checking Objective-C %@ format specification
1034    assert fails(stdchecker.printf, "I am %@", "Ek is @%")  # typo
1035    assert fails(
1036        stdchecker.printf, "Object %@ and object %@", "String %1$@ en string %3$@"
1037    )  # out of bounds
1038    assert fails(stdchecker.printf, "I am %@", "Ek is %s")  # wrong specification
1039    assert passes(
1040        stdchecker.printf, "Object %@ and string %s", "Object %1$@ en string %2$s"
1041    )  # correct sentence
1042    # Checking boost format.
1043    # Boost classic printf.
1044    assert passes(
1045        stdchecker.printf,
1046        "writing %1%,  x=%2% : %3%-th try",
1047        "escribindo %1%,  x=%2% : %3%-esimo intento",
1048    )
1049    # Reordering boost.
1050    assert passes(stdchecker.printf, "%1% %2% %3% %2% %1%", "%1% %2% %3% %2% %1%")
1051    # Boost posix format.
1052    assert passes(
1053        stdchecker.printf, "(x,y) = (%1$+5d,%2$+5d)", "(x,y) = (%1$+5d,%2$+5d)"
1054    )
1055    # Boost several ways to express the same.
1056    assert passes(stdchecker.printf, "(x,y) = (%+5d,%+5d)", "(x,y) = (%+5d,%+5d)")
1057    assert passes(stdchecker.printf, "(x,y) = (%|+5|,%|+5|)", "(x,y) = (%|+5|,%|+5|)")
1058    assert passes(
1059        stdchecker.printf, "(x,y) = (%1$+5d,%2$+5d)", "(x,y) = (%1$+5d,%2$+5d)"
1060    )
1061    assert passes(
1062        stdchecker.printf, "(x,y) = (%|1$+5|,%|2$+5|)", "(x,y) = (%|1$+5|,%|2$+5|)"
1063    )
1064    # Boost using manipulators.
1065    assert passes(
1066        stdchecker.printf, "_%1$+5d_ %1$d", "_%1$+5d_ %1$d"
1067    )  # This is failing.
1068    assert passes(stdchecker.printf, "_%1%_ %1%", "_%1%_ %1%")
1069    # Boost absolute tabulations.
1070    assert passes(stdchecker.printf, "%1%, %2%, %|40t|%3%", "%1%, %2%, %|40t|%3%")
1071
1072
1073def test_pythonbraceformat():
1074    """Tests python brace format placeholder"""
1075    stdchecker = checks.StandardChecker()
1076    # anonymous formats
1077    assert passes(
1078        stdchecker.pythonbraceformat,
1079        "String {} and number {}",
1080        "String {} en nommer {}",
1081    )
1082    assert passes(stdchecker.pythonbraceformat, "String {1}", "Nommer {} en string {}")
1083    assert passes(
1084        stdchecker.pythonbraceformat,
1085        "String {1} and number {0}",
1086        "Nommer {0} en string {1}",
1087    )
1088    assert fails(stdchecker.pythonbraceformat, "String {}, {}", "String {}")
1089    assert fails_serious(
1090        stdchecker.pythonbraceformat, "String {}", "String {} en nommer {}"
1091    )
1092    assert fails_serious(stdchecker.pythonbraceformat, "String {}", "Nommer {1}")
1093    assert fails_serious(stdchecker.pythonbraceformat, "String {0}", "Nommer {1}")
1094    assert fails_serious(stdchecker.pythonbraceformat, "String {0} {}", "Nommer {1}")
1095    lochecker = checks.LibreOfficeChecker()
1096    assert passes(
1097        lochecker.pythonbraceformat,
1098        "Time remaining: {[1] minutes }{[2] seconds}",
1099        "Tenpo che'l resta: {[1] minuti}{[2] secondi}",
1100    )
1101
1102    # Named formats
1103    assert passes(
1104        stdchecker.pythonbraceformat,
1105        "String {str} and number {num}",
1106        "Nommer {num} en string {str}",
1107    )
1108    # TODO: check for a mixture of substitution techniques
1109    assert fails(
1110        stdchecker.pythonbraceformat,
1111        "String {str} and number {num}",
1112        "Nommer {num} en string %s",
1113    )
1114    assert fails_serious(
1115        stdchecker.pythonbraceformat,
1116        "String {str} and number {num}",
1117        "Nommer {onbekend} en string {str}",
1118    )
1119
1120
1121def test_puncspacing():
1122    """tests spacing after punctuation"""
1123    stdchecker = checks.StandardChecker()
1124    assert passes(
1125        stdchecker.puncspacing, "One, two, three.", "Kunye, kubili, kuthathu."
1126    )
1127    assert passes(
1128        stdchecker.puncspacing, "One, two, three. ", "Kunye, kubili, kuthathu."
1129    )
1130    assert fails(stdchecker.puncspacing, "One, two, three. ", "Kunye, kubili,kuthathu.")
1131    assert passes(
1132        stdchecker.puncspacing, "One, two, three!?", "Kunye, kubili, kuthathu?"
1133    )
1134
1135    # Some languages have padded puntuation marks
1136    frchecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="fr"))
1137    assert passes(frchecker.puncspacing, 'Do "this"', "Do « this »")
1138    assert passes(frchecker.puncspacing, 'Do "this"', "Do «\u00a0this\u00a0»")
1139    assert fails(frchecker.puncspacing, 'Do "this"', "Do «this»")
1140
1141    # Handle Bidi markers as non-characters
1142    hechecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="he"))
1143    assert passes(hechecker.puncspacing, "hi. there", "שלום.\u200f לך")  # RLM
1144    assert passes(hechecker.puncspacing, "hi. there", "שלום.\u200e לך")  # LRM
1145    assert passes(hechecker.puncspacing, "hi. there", "שלום.\u202b לך")  # RLE
1146    assert passes(hechecker.puncspacing, "hi. there", "שלום.\u202a לך")  # LRE
1147    assert passes(hechecker.puncspacing, "hi. there", "שלום.\u202e לך")  # RLO
1148    assert passes(hechecker.puncspacing, "hi. there", "שלום.\u202d לך")  # LRO
1149    assert passes(hechecker.puncspacing, "hi. there", "שלום.\u202c לך")  # PDF
1150    assert passes(hechecker.puncspacing, "hi. there", "שלום.\u2069 לך")  # PDI
1151    assert passes(hechecker.puncspacing, "hi. there", "שלום.\u2068 לך")  # FSI
1152    assert passes(hechecker.puncspacing, "hi. there", "שלום.\u2067 לך")  # RLI
1153    assert passes(hechecker.puncspacing, "hi. there", "שלום.\u2066 לך")  # LRI
1154
1155    # ZWJ and ZWNJ handling as non-characters
1156    archecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="ar"))
1157    assert passes(archecker.puncspacing, "hi. there", "السلام.\u200d عليكم")  # ZWJ
1158    assert passes(archecker.puncspacing, "hi. there", "السلام.\u200c عليكم")  # ZWNJ
1159
1160
1161def test_purepunc():
1162    """tests messages containing only punctuation"""
1163    stdchecker = checks.StandardChecker()
1164    assert passes(stdchecker.purepunc, ".", ".")
1165    assert passes(stdchecker.purepunc, "", "")
1166    assert fails(stdchecker.purepunc, ".", " ")
1167    assert fails(stdchecker.purepunc, "Find", "'")
1168    assert fails(stdchecker.purepunc, "'", "Find")
1169    assert passes(stdchecker.purepunc, "year measurement template|2000", "2000")
1170
1171
1172def test_sentencecount():
1173    """tests sentencecount messages"""
1174    stdchecker = checks.StandardChecker()
1175    assert passes(stdchecker.sentencecount, "One. Two. Three.", "Een. Twee. Drie.")
1176    assert passes(stdchecker.sentencecount, "One two three", "Een twee drie.")
1177    assert fails(stdchecker.sentencecount, "One. Two. Three.", "Een Twee. Drie.")
1178    assert passes(
1179        stdchecker.sentencecount, "Sentence with i.e. in it.", "Sin met d.w.s. in dit."
1180    )  # bug 178, description item 8
1181    el_checker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="el"))
1182    assert fails(
1183        el_checker.sentencecount,
1184        "First sentence. Second sentence.",
1185        "Πρώτη πρόταση. δεύτερη πρόταση.",
1186    )
1187
1188
1189def test_short():
1190    """tests short messages"""
1191    stdchecker = checks.StandardChecker()
1192    assert passes(stdchecker.short, "I am normal", "Ek is ook normaal")
1193    assert fails(stdchecker.short, "I am a very long sentence", "Ek")
1194    assert fails(stdchecker.short, "abcde", "c")
1195
1196
1197def test_singlequoting():
1198    """tests single quotes"""
1199    stdchecker = checks.StandardChecker()
1200    assert passes(stdchecker.singlequoting, "A 'Hot' plate", "Ipuleti 'elishisa' kunye")
1201    # FIXME this should pass but doesn't probably to do with our logic that got confused at the end of lines
1202    assert passes(stdchecker.singlequoting, "'Hot' plate", "Ipuleti 'elishisa'")
1203    # FIXME newlines also confuse our algorithm for single quotes
1204    assert passes(stdchecker.singlequoting, "File '%s'\n", "'%s' Faele\n")
1205    assert fails(stdchecker.singlequoting, "'Hot' plate", 'Ipuleti "elishisa"')
1206    assert passes(stdchecker.singlequoting, "It's here.", "Dit is hier.")
1207    # Don't get confused by punctuation that touches a single quote
1208    assert passes(stdchecker.singlequoting, "File '%s'.", "'%s' Faele.")
1209    assert passes(
1210        stdchecker.singlequoting, "Blah 'format' blah.", "Blah blah 'sebopego'."
1211    )
1212    assert passes(
1213        stdchecker.singlequoting, "Blah 'format' blah!", "Blah blah 'sebopego'!"
1214    )
1215    assert passes(
1216        stdchecker.singlequoting, "Blah 'format' blah?", "Blah blah 'sebopego'?"
1217    )
1218    # Real examples
1219    assert passes(
1220        stdchecker.singlequoting,
1221        "A nickname that identifies this publishing site (e.g.: 'MySite')",
1222        "Vito ro duvulela leri tirhisiwaka ku kuma sayiti leri ro kandziyisa (xik.: 'Sayiti ra Mina')",
1223    )
1224    assert passes(stdchecker.singlequoting, "isn't", "ayikho")
1225    assert passes(
1226        stdchecker.singlequoting,
1227        "Required (can't send message unless all recipients have certificates)",
1228        "Verlang (kan nie boodskappe versend tensy al die ontvangers sertifikate het nie)",
1229    )
1230    # Afrikaans 'n
1231    assert passes(
1232        stdchecker.singlequoting,
1233        "Please enter a different site name.",
1234        "Tik 'n ander werfnaam in.",
1235    )
1236    assert passes(
1237        stdchecker.singlequoting,
1238        '"%name%" already exists. Please enter a different site name.',
1239        '"%name%" bestaan reeds. Tik \'n ander werfnaam in.',
1240    )
1241    # Check that accelerators don't mess with removing singlequotes
1242    mozillachecker = checks.MozillaChecker()
1243    assert passes(
1244        mozillachecker.singlequoting,
1245        "&Don't import anything",
1246        "&Moenie enigiets invoer nie",
1247    )
1248    ooochecker = checks.OpenOfficeChecker()
1249    assert passes(
1250        ooochecker.singlequoting,
1251        "~Don't import anything",
1252        "~Moenie enigiets invoer nie",
1253    )
1254    lochecker = checks.LibreOfficeChecker()
1255    assert passes(
1256        lochecker.singlequoting, "~Don't import anything", "~Moenie enigiets invoer nie"
1257    )
1258
1259
1260def test_vietnamese_singlequoting():
1261    vichecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="vi"))
1262    assert passes(vichecker.singlequoting, "Save 'File'", "Lưu « Tập tin »")
1263    assert passes(vichecker.singlequoting, "Save `File'", "Lưu « Tập tin »")
1264
1265
1266@mark.xfail(reason="Bug #3408")
1267def test_persian_single_and_double_quote_fail_at_the_same_time():
1268    """Test Persian single and double quote failures in string with single quotes."""
1269    checker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="fa"))
1270
1271    # With single quote check.
1272    assert fails(checker.singlequoting, "Path: '%S'", "مسیر: '%S'‎")
1273    assert fails(checker.singlequoting, "Path: '%S'", 'مسیر: "%S"‎')
1274    assert passes(checker.singlequoting, "Path: '%S'", "مسیر: «%S»")
1275
1276    # With double quote check.
1277    assert passes(checker.doublequoting, "Path: '%S'", "مسیر: '%S'‎")
1278    assert passes(checker.doublequoting, "Path: '%S'", 'مسیر: "%S"‎')
1279    assert passes(checker.doublequoting, "Path: '%S'", "مسیر: «%S»")
1280
1281
1282def test_persian_quoting():
1283    """Test single and double quoting for Persian."""
1284    checker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="fa"))
1285
1286    # Just double quoting.
1287    assert fails(checker.doublequoting, 'Path: "%S"', "مسیر: '%S'‎")
1288    assert fails(checker.doublequoting, 'Path: "%S"', 'مسیر: "%S"‎')
1289    assert passes(checker.doublequoting, 'Path: "%S"', "مسیر: «%S»")
1290
1291    # Just XML quoting.
1292    assert passes(
1293        checker.singlequoting, '<area shape="circle">', '<area shape="circle">'
1294    )
1295    assert passes(
1296        checker.doublequoting, '<area shape="circle">', '<area shape="circle">'
1297    )
1298
1299    # XML quoting and double quoting.
1300    assert passes(
1301        checker.singlequoting,
1302        'The "coords" attribute of the <area shape="circle"> tag has a negative radius.',
1303        'مشخصهٔ «coords» برچسب ‪<area shape="circle">‬ دارای «radius» منفی است.',
1304    )
1305    assert passes(
1306        checker.doublequoting,
1307        'The "coords" attribute of the <area shape="circle"> tag has a negative "radius".',
1308        'مشخصهٔ «coords» برچسب ‪<area shape="circle">‬ دارای «radius» منفی است.',
1309    )
1310
1311    # Single quotes with variables in source fails both single and double quote
1312    # checks.
1313    assert fails(
1314        checker.singlequoting, "'%1$S' is not a directory", "'%1$S' یک شاخه نیست"
1315    )
1316    # TODO the following should fail.
1317    assert passes(
1318        checker.singlequoting, "'%1$S' is not a directory", '"%1$S" یک شاخه نیست'
1319    )
1320    assert fails(
1321        checker.doublequoting, "'%1$S' is not a directory", "'%1$S' یک شاخه نیست"
1322    )
1323    assert fails(
1324        checker.doublequoting, "'%1$S' is not a directory", '"%1$S" یک شاخه نیست'
1325    )
1326    # But works when using the right quoting in translation.
1327    assert passes(
1328        checker.singlequoting, "'%1$S' is not a directory", "«%1$S» یک شاخه نیست"
1329    )
1330    assert passes(
1331        checker.doublequoting, "'%1$S' is not a directory", "«%1$S» یک شاخه نیست"
1332    )
1333
1334    # Mixing single quotes and and single quotes that shouldn't be translated.
1335    assert fails(
1336        checker.singlequoting, "Can't find property '%S'", "خاصیت '%S' یافت نشد"
1337    )
1338    assert passes(
1339        checker.singlequoting, "Can't find property '%S'", "خاصیت «%S» یافت نشد"
1340    )
1341
1342    # Mixed single quotes do not trigger double quote check.
1343    assert passes(
1344        checker.doublequoting, "Can't find property '%S'", "خاصیت '%S' یافت نشد"
1345    )
1346    # TODO the following should pass.
1347    assert fails(
1348        checker.doublequoting, "Can't find property '%S'", "خاصیت «%S» یافت نشد"
1349    )
1350
1351    # Single quotes that are not errors pass.
1352    assert passes(
1353        checker.singlequoting,
1354        "Request the version of a user's client.",
1355        "درخواست نسخه کلاینت کاربر.",
1356    )
1357    assert passes(
1358        checker.doublequoting,
1359        "Request the version of a user's client.",
1360        "درخواست نسخه کلاینت کاربر.",
1361    )
1362
1363
1364def test_simplecaps():
1365    """tests simple caps"""
1366    # Simple caps is a very vauge test so the checks here are mostly for obviously fixable problem
1367    # or for checking obviously correct situations that are triggering a failure.
1368    stdchecker = checks.StandardChecker()
1369    assert passes(
1370        stdchecker.simplecaps,
1371        "MB of disk space for the cache.",
1372        "MB yendzawo yediski etsala.",
1373    )
1374    # We should squash 'I' in the source text as it messes with capital detection
1375    assert passes(stdchecker.simplecaps, "if you say I want", "as jy se ek wil")
1376    assert passes(
1377        stdchecker.simplecaps, "sentence. I want more.", "sin. Ek wil meer he."
1378    )
1379    assert passes(
1380        stdchecker.simplecaps,
1381        "Where are we? I can't see where we are going.",
1382        "Waar is ons? Ek kan nie sien waar ons gaan nie.",
1383    )
1384    ## We should remove variables before checking
1385    stdchecker = checks.StandardChecker(checks.CheckerConfig(varmatches=[("%", 1)]))
1386    assert passes(
1387        stdchecker.simplecaps, "Could not load %s", "A swi koteki ku panga %S"
1388    )
1389    assert passes(
1390        stdchecker.simplecaps,
1391        'The element "%S" is not recognized.',
1392        'Elemente "%S" a yi tiveki.',
1393    )
1394    stdchecker = checks.StandardChecker(checks.CheckerConfig(varmatches=[("&", ";")]))
1395    assert passes(
1396        stdchecker.simplecaps,
1397        "Determine how &brandShortName; connects to the Internet.",
1398        "Kuma &brandShortName; hlanganisa eka Internete.",
1399    )
1400    ## If source is ALL CAPS then we should just check that target is also ALL CAPS
1401    assert passes(stdchecker.simplecaps, "COUPDAYS", "COUPMALANGA")
1402    # Just some that at times have failed but should always pass
1403    assert passes(
1404        stdchecker.simplecaps,
1405        "Create a query  entering an SQL statement directly.",
1406        "Yakha sibuti singena SQL inkhomba yesitatimende.",
1407    )
1408    ooochecker = checks.OpenOfficeChecker()
1409    assert passes(
1410        ooochecker.simplecaps,
1411        "SOLK (%PRODUCTNAME Link)",
1412        "SOLK (%PRODUCTNAME Thumanyo)",
1413    )
1414    assert passes(
1415        ooochecker.simplecaps, "%STAROFFICE Image", "Tshifanyiso tsha %STAROFFICE"
1416    )
1417    lochecker = checks.LibreOfficeChecker()
1418    assert passes(
1419        lochecker.simplecaps, "SOLK (%PRODUCTNAME Link)", "SOLK (%PRODUCTNAME Thumanyo)"
1420    )
1421    assert passes(
1422        lochecker.simplecaps, "%STAROFFICE Image", "Tshifanyiso tsha %STAROFFICE"
1423    )
1424    assert passes(
1425        stdchecker.simplecaps,
1426        "Flies, flies, everywhere! Ack!",
1427        "Vlieë, oral vlieë! Jig!",
1428    )
1429
1430
1431@mark.skipif(
1432    not spelling.available or not spelling._get_checker("af"),
1433    reason="Spell checking for af is not available",
1434)
1435def test_spellcheck():
1436    """tests spell checking"""
1437    stdchecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="af"))
1438    assert passes(stdchecker.spellcheck, "Great trek", "Groot trek")
1439    assert fails(stdchecker.spellcheck, "Final deadline", "End of the road")
1440    # Bug 289: filters accelerators before spell checking
1441    stdchecker = checks.StandardChecker(
1442        checks.CheckerConfig(accelmarkers="&", targetlanguage="fi")
1443    )
1444    assert passes(stdchecker.spellcheck, "&Reload Frame", "P&äivitä kehys")
1445    # Ensure we don't check notranslatewords
1446    stdchecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="af"))
1447    assert fails(
1448        stdchecker.spellcheck, "Mozilla is wonderful", "Mozillaaa is wonderlik"
1449    )
1450    # We should pass the test if the "error" occurs in the English
1451    assert passes(
1452        stdchecker.spellcheck, "Mozillaxxx is wonderful", "Mozillaxxx is wonderlik"
1453    )
1454    stdchecker = checks.StandardChecker(
1455        checks.CheckerConfig(targetlanguage="af", notranslatewords=["Mozilla"])
1456    )
1457    assert passes(stdchecker.spellcheck, "Mozilla is wonderful", "Mozilla is wonderlik")
1458    # Some variables were still being spell checked
1459    mozillachecker = checks.MozillaChecker(
1460        checkerconfig=checks.CheckerConfig(targetlanguage="af")
1461    )
1462    assert passes(
1463        mozillachecker.spellcheck,
1464        "&brandShortName.labels; is wonderful",
1465        "&brandShortName.label; is wonderlik",
1466    )
1467
1468
1469def test_startcaps():
1470    """tests starting capitals"""
1471    stdchecker = checks.StandardChecker()
1472    assert passes(stdchecker.startcaps, "Find", "Vind")
1473    assert passes(stdchecker.startcaps, "find", "vind")
1474    assert fails(stdchecker.startcaps, "Find", "vind")
1475    assert fails(stdchecker.startcaps, "find", "Vind")
1476    assert passes(stdchecker.startcaps, "'", "'")
1477    assert passes(
1478        stdchecker.startcaps,
1479        "\\.,/?!`'\"[]{}()@#$%^&*_-;:<>Find",
1480        "\\.,/?!`'\"[]{}()@#$%^&*_-;:<>Vind",
1481    )
1482    # With leading whitespace
1483    assert passes(stdchecker.startcaps, " Find", " Vind")
1484    assert passes(stdchecker.startcaps, " find", " vind")
1485    assert fails(stdchecker.startcaps, " Find", " vind")
1486    assert fails(stdchecker.startcaps, " find", " Vind")
1487    # Leading punctuation
1488    assert passes(stdchecker.startcaps, "'Find", "'Vind")
1489    assert passes(stdchecker.startcaps, "'find", "'vind")
1490    assert fails(stdchecker.startcaps, "'Find", "'vind")
1491    assert fails(stdchecker.startcaps, "'find", "'Vind")
1492    # Unicode
1493    assert passes(stdchecker.startcaps, "Find", "Šind")
1494    assert passes(stdchecker.startcaps, "find", "šind")
1495    assert fails(stdchecker.startcaps, "Find", "šind")
1496    assert fails(stdchecker.startcaps, "find", "Šind")
1497    # Unicode further down the Unicode tables
1498    assert passes(
1499        stdchecker.startcaps, "A text enclosed...", "Ḽiṅwalwa ḽo katelwaho..."
1500    )
1501    assert fails(stdchecker.startcaps, "A text enclosed...", "ḽiṅwalwa ḽo katelwaho...")
1502    # Accelerators
1503    stdchecker = checks.StandardChecker(checks.CheckerConfig(accelmarkers="&"))
1504    assert passes(stdchecker.startcaps, "&Find", "Vi&nd")
1505    # Numbers - we really can't tell what should happen with numbers, so ignore
1506    # source or target that start with a number
1507    assert passes(stdchecker.startcaps, "360 degrees", "Grade 360")
1508    assert passes(stdchecker.startcaps, "360 degrees", "grade 360")
1509
1510    # Language specific stuff
1511    afchecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="af"))
1512    assert passes(afchecker.startcaps, "A cow", "'n Koei")
1513    assert passes(afchecker.startcaps, "A list of ", "'n Lys van ")
1514    # should pass:
1515    # assert passes(afchecker.startcaps, "A 1k file", "'n 1k-lêer")
1516    assert passes(afchecker.startcaps, "'Do it'", "'Doen dit'")
1517    assert fails(afchecker.startcaps, "'Closer than'", "'nader as'")
1518    assert passes(afchecker.startcaps, "List", "Lys")
1519    assert passes(afchecker.startcaps, "a cow", "'n koei")
1520    assert fails(afchecker.startcaps, "a cow", "'n Koei")
1521    assert passes(afchecker.startcaps, "(A cow)", "('n Koei)")
1522    assert fails(afchecker.startcaps, "(a cow)", "('n Koei)")
1523
1524
1525def test_startpunc():
1526    """tests startpunc"""
1527    stdchecker = checks.StandardChecker()
1528    assert passes(stdchecker.startpunc, "<< Previous", "<< Correct")
1529    assert fails(stdchecker.startpunc, " << Previous", "Wrong")
1530    assert fails(stdchecker.startpunc, "Question", "\u2026Wrong")
1531
1532    assert passes(
1533        stdchecker.startpunc, "<fish>hello</fish> world", "world <fish>hello</fish>"
1534    )
1535
1536    # The inverted Spanish question mark should be accepted
1537    stdchecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="es"))
1538    assert passes(
1539        stdchecker.startpunc,
1540        "Do you want to reload the file?",
1541        "¿Quiere recargar el archivo?",
1542    )
1543
1544    # The Afrikaans indefinite article should be accepted
1545    stdchecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="af"))
1546    assert passes(stdchecker.startpunc, "A human?", "'n Mens?")
1547
1548
1549def test_startwhitespace():
1550    """tests startwhitespace"""
1551    stdchecker = checks.StandardChecker()
1552    assert passes(stdchecker.startwhitespace, "A setence.", "I'm correct.")
1553    assert fails(stdchecker.startwhitespace, " A setence.", "I'm incorrect.")
1554
1555
1556def test_unchanged():
1557    """tests unchanged entries"""
1558    stdchecker = checks.StandardChecker(checks.CheckerConfig(accelmarkers="&"))
1559    assert fails(stdchecker.unchanged, "Unchanged", "Unchanged")
1560    assert fails(stdchecker.unchanged, "&Unchanged", "Un&changed")
1561    assert passes(stdchecker.unchanged, "Unchanged", "Changed")
1562    assert passes(stdchecker.unchanged, "1234", "1234")
1563    assert passes(stdchecker.unchanged, "2×2", "2×2")  # bug 178, description item 14
1564    assert passes(stdchecker.unchanged, "I", "I")
1565    assert passes(stdchecker.unchanged, "   ", "   ")  # bug 178, description item 5
1566    assert passes(stdchecker.unchanged, "???", "???")  # bug 178, description item 15
1567    assert passes(
1568        stdchecker.unchanged, "&ACRONYM", "&ACRONYM"
1569    )  # bug 178, description item 7
1570    assert passes(stdchecker.unchanged, "F1", "F1")  # bug 178, description item 20
1571    assert fails(stdchecker.unchanged, "Two words", "Two words")
1572    # TODO: this still fails
1573    #    assert passes(stdchecker.unchanged, "NOMINAL", "NOMİNAL")
1574    gnomechecker = checks.GnomeChecker()
1575    assert fails(
1576        gnomechecker.unchanged,
1577        "Entity references, such as &amp; and &#169;",
1578        "Entity references, such as &amp; and &#169;",
1579    )
1580    # Variable only and variable plus punctuation messages should be ignored
1581    mozillachecker = checks.MozillaChecker()
1582    assert passes(mozillachecker.unchanged, "$ProgramName$", "$ProgramName$")
1583    assert passes(
1584        mozillachecker.unchanged, "$file$ : $dir$", "$file$ : $dir$"
1585    )  # bug 178, description item 13
1586    assert fails(mozillachecker.unchanged, "$file$ in $dir$", "$file$ in $dir$")
1587    assert passes(mozillachecker.unchanged, "&brandShortName;", "&brandShortName;")
1588    # Don't translate words should be ignored
1589    stdchecker = checks.StandardChecker(
1590        checks.CheckerConfig(notranslatewords=["Mozilla"])
1591    )
1592    assert passes(
1593        stdchecker.unchanged, "Mozilla", "Mozilla"
1594    )  # bug 178, description item 10
1595    # Don't fail unchanged if the entry is a dialogsize, quite plausible that you won't change it
1596    mozillachecker = checks.MozillaChecker()
1597    assert passes(mozillachecker.unchanged, "width: 12em;", "width: 12em;")
1598    assert fails(stdchecker.unchanged, "width: 12em;", "width: 12em;")
1599    assert passes(mozillachecker.unchanged, "7em", "7em")
1600    assert fails(stdchecker.unchanged, "7em", "7em")
1601
1602
1603def test_untranslated():
1604    """tests untranslated entries"""
1605    stdchecker = checks.StandardChecker()
1606    assert fails(stdchecker.untranslated, "I am untranslated", "")
1607    assert passes(stdchecker.untranslated, "I am translated", "Ek is vertaal")
1608    # KDE comments that make it into translations should not mask untranslated test
1609    assert fails(
1610        stdchecker.untranslated,
1611        "_: KDE comment\\n\nI am untranslated",
1612        "_: KDE comment\\n\n",
1613    )
1614
1615
1616def test_validchars():
1617    """tests valid characters"""
1618    stdchecker = checks.StandardChecker(checks.CheckerConfig())
1619    assert passes(
1620        stdchecker.validchars,
1621        "The check always passes if you don't specify chars",
1622        "Die toets sal altyd werk as jy nie karacters specifisier",
1623    )
1624    stdchecker = checks.StandardChecker(
1625        checks.CheckerConfig(
1626            validchars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
1627        )
1628    )
1629    assert passes(
1630        stdchecker.validchars,
1631        "This sentence contains valid characters",
1632        "Hierdie sin bevat ware karakters",
1633    )
1634    assert fails(stdchecker.validchars, "Some unexpected characters", "©®°±÷¼½¾")
1635    stdchecker = checks.StandardChecker(
1636        checks.CheckerConfig(
1637            validchars="⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰"
1638        )
1639    )
1640    assert passes(
1641        stdchecker.validchars,
1642        "Our target language is all non-ascii",
1643        "⠁⠂⠃⠄⠆⠇⠈⠉⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫",
1644    )
1645    assert fails(
1646        stdchecker.validchars,
1647        "Our target language is all non-ascii",
1648        "Some ascii⠁⠂⠃⠄⠆⠇⠈⠉⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫",
1649    )
1650    stdchecker = checks.StandardChecker(checks.CheckerConfig(validchars="\u004c\u032d"))
1651    assert passes(
1652        stdchecker.validchars, "This sentence contains valid chars", "\u004c\u032d"
1653    )
1654    assert passes(stdchecker.validchars, "This sentence contains valid chars", "\u1e3c")
1655    stdchecker = checks.StandardChecker(checks.CheckerConfig(validchars="\u1e3c"))
1656    assert passes(stdchecker.validchars, "This sentence contains valid chars", "\u1e3c")
1657    assert passes(
1658        stdchecker.validchars, "This sentence contains valid chars", "\u004c\u032d"
1659    )
1660
1661
1662def test_minimalchecker():
1663    """tests the Minimal quality checker"""
1664    from translate.storage import base
1665
1666    # The minimal checker only checks for untranslated, unchanged and blank strings.
1667    # All other quality checks should be ignored.
1668    minimalchecker = checks.MinimalChecker()
1669    assert fails(minimalchecker.untranslated, "I am untranslated", "")
1670    assert passes(minimalchecker.untranslated, "I am translated", "Ek is vertaal")
1671    assert fails(minimalchecker.unchanged, "Unchanged", "Unchanged")
1672    assert passes(minimalchecker.unchanged, "Unchanged", "Changed")
1673    assert fails(minimalchecker.blank, "Blank string", " ")
1674
1675    # Doublewords check is disabled.
1676    src, tgt, __ = strprep("Save the rhino", "Save the the rhino")
1677    unit = base.TranslationUnit(src)
1678    unit.target = tgt
1679
1680    assert "doublewords" not in minimalchecker.run_filters(unit).keys()
1681
1682    # Printf check is disabled.
1683    src, tgt, __ = strprep("Non-matching printf variables", "Ek is %s")
1684    unit = base.TranslationUnit(src)
1685    unit.target = tgt
1686
1687    assert "printf" not in minimalchecker.run_filters(unit).keys()
1688
1689
1690def test_reducedchecker():
1691    """tests the Reduced quality checker"""
1692    from translate.storage import base
1693
1694    # The reduced checker only runs the following tests:
1695    # untranslated, unchanged, blank, doublespacing, doublewords, spellcheck.
1696    # All other quality checks should be ignored.
1697    reducedchecker = checks.ReducedChecker()
1698    assert fails(reducedchecker.untranslated, "I am untranslated", "")
1699    assert passes(reducedchecker.untranslated, "I am translated", "Ek is vertaal")
1700    assert fails(reducedchecker.unchanged, "Unchanged", "Unchanged")
1701    assert passes(reducedchecker.unchanged, "Unchanged", "Changed")
1702    assert fails(reducedchecker.blank, "Blank string", " ")
1703    assert passes(
1704        reducedchecker.doublespacing,
1705        "Sentence. Another sentence.",
1706        "Sin. No double spacing.",
1707    )
1708    assert fails(
1709        reducedchecker.doublespacing,
1710        "Sentence. Another sentence.",
1711        "Sin.  Uneeded double space in translation.",
1712    )
1713    assert passes(reducedchecker.doublewords, "Save the rhino", "Save the rhino")
1714    assert fails(reducedchecker.doublewords, "Save the rhino", "Save the the rhino")
1715
1716    # Printf check is disabled.
1717    src, tgt, __ = strprep("Non-matching printf variables", "Ek is %s")
1718    unit = base.TranslationUnit(src)
1719    unit.target = tgt
1720
1721    assert "printf" not in reducedchecker.run_filters(unit).keys()
1722
1723    # Escapes check is disabled.
1724    src, tgt, __ = strprep("A file", "'n Leer\n")
1725    unit = base.TranslationUnit(src)
1726    unit.target = tgt
1727
1728    assert "escapes" not in reducedchecker.run_filters(unit).keys()
1729
1730
1731def test_variables_kde():
1732    """tests variables in KDE translations"""
1733    # GNOME variables
1734    kdechecker = checks.KdeChecker()
1735    assert passes(
1736        kdechecker.variables,
1737        "%d files of type %s saved.",
1738        "%d leers van %s tipe gestoor.",
1739    )
1740    assert fails_serious(
1741        kdechecker.variables,
1742        "%d files of type %s saved.",
1743        "%s leers van %s tipe gestoor.",
1744    )
1745
1746
1747def test_variables_gnome():
1748    """tests variables in GNOME translations"""
1749    # GNOME variables
1750    gnomechecker = checks.GnomeChecker()
1751    assert passes(
1752        gnomechecker.variables,
1753        "%d files of type %s saved.",
1754        "%d leers van %s tipe gestoor.",
1755    )
1756    assert fails_serious(
1757        gnomechecker.variables,
1758        "%d files of type %s saved.",
1759        "%s leers van %s tipe gestoor.",
1760    )
1761    assert passes(gnomechecker.variables, "Save $(file)", "Stoor $(file)")
1762    assert fails_serious(gnomechecker.variables, "Save $(file)", "Stoor $(leer)")
1763
1764
1765def test_variables_mozilla():
1766    """tests variables in Mozilla translations"""
1767    # Mozilla variables
1768    mozillachecker = checks.MozillaChecker()
1769    assert passes(
1770        mozillachecker.variables,
1771        "Use the &brandShortname; instance.",
1772        "Gebruik die &brandShortname; weergawe.",
1773    )
1774    assert fails_serious(
1775        mozillachecker.variables,
1776        "Use the &brandShortname; instance.",
1777        "Gebruik die &brandKortnaam; weergawe.",
1778    )
1779    assert passes(mozillachecker.variables, "Save %file%", "Stoor %file%")
1780    assert fails_serious(mozillachecker.variables, "Save %file%", "Stoor %leer%")
1781    assert passes(mozillachecker.variables, "Save $file$", "Stoor $file$")
1782    assert fails_serious(mozillachecker.variables, "Save $file$", "Stoor $leer$")
1783    assert passes(
1784        mozillachecker.variables,
1785        "%d files of type %s saved.",
1786        "%d leers van %s tipe gestoor.",
1787    )
1788    assert fails_serious(
1789        mozillachecker.variables,
1790        "%d files of type %s saved.",
1791        "%s leers van %s tipe gestoor.",
1792    )
1793    assert passes(mozillachecker.variables, "Save $file", "Stoor $file")
1794    assert fails_serious(mozillachecker.variables, "Save $file", "Stoor $leer")
1795    assert passes(mozillachecker.variables, "About $ProgramName$", "Oor $ProgramName$")
1796    assert fails_serious(
1797        mozillachecker.variables, "About $ProgramName$", "Oor $NaamVanProgam$"
1798    )
1799    assert passes(mozillachecker.variables, "About $_CLICK", "Oor $_CLICK")
1800    assert fails_serious(mozillachecker.variables, "About $_CLICK", "Oor $_KLIK")
1801    assert passes(
1802        mozillachecker.variables, "About $_CLICK and more", "Oor $_CLICK en meer"
1803    )
1804    assert fails_serious(
1805        mozillachecker.variables, "About $_CLICK and more", "Oor $_KLIK en meer"
1806    )
1807    assert passes(mozillachecker.variables, "About $(^NameDA)", "Oor $(^NameDA)")
1808    assert fails_serious(mozillachecker.variables, "About $(^NameDA)", "Oor $(^NaamDA)")
1809    assert passes(
1810        mozillachecker.variables,
1811        "Open {{pageCount}} pages",
1812        "Make {{pageCount}} bladsye oop",
1813    )
1814    assert fails_serious(
1815        mozillachecker.variables,
1816        "Open {{pageCount}} pages",
1817        "Make {{bladTelling}} bladsye oop",
1818    )
1819    # Double variable problem
1820    assert fails_serious(
1821        mozillachecker.variables, "Create In &lt;&lt;", "Etsa ka Ho &lt;lt;"
1822    )
1823    # Variables at the end of a sentence
1824    assert fails_serious(
1825        mozillachecker.variables,
1826        "...time you start &brandShortName;.",
1827        "...lekgetlo le latelang ha o qala &LebitsoKgutshwane la kgwebo;.",
1828    )
1829    # Ensure that we can detect two variables of the same name with one faulty
1830    assert fails_serious(
1831        mozillachecker.variables,
1832        "&brandShortName; successfully downloaded and installed updates. You will have to restart &brandShortName; to complete the update.",
1833        "&brandShortName; ḽo dzhenisa na u longela khwinifhadzo zwavhuḓi. Ni ḓo tea u thoma hafhu &DzinaḼipfufhi ḽa pfungavhuṇe; u itela u fhedzisa khwinifha dzo.",
1834    )
1835    # We must detect entities in their fullform, ie with fullstop in the middle.
1836    assert fails_serious(
1837        mozillachecker.variables,
1838        "Welcome to the &pluginWizard.title;",
1839        "Wamkelekile kwi&Sihloko Soncedo lwe-plugin;",
1840    )
1841    # Variables that are missing in quotes should be detected
1842    assert fails_serious(
1843        mozillachecker.variables,
1844        '"%S" is an executable file.... Are you sure you want to launch "%S"?',
1845        '.... Uyaqiniseka ukuthi ufuna ukuqalisa I"%S"?',
1846    )
1847    # False positive $ style variables
1848    assert passes(
1849        mozillachecker.variables,
1850        "for reporting $ProductShortName$ crash information",
1851        "okokubika ukwaziswa kokumosheka kwe-$ProductShortName$",
1852    )
1853    # We shouldn't mask variables within variables.  This should highlight &brandShortName as missing and &amp as extra
1854    assert fails_serious(
1855        mozillachecker.variables, "&brandShortName;", "&amp;brandShortName;"
1856    )
1857
1858
1859def test_variables_openoffice():
1860    """tests variables in OpenOffice translations"""
1861    # OpenOffice.org variables
1862    for ooochecker in (checks.OpenOfficeChecker(), checks.LibreOfficeChecker()):
1863        assert passes(
1864            ooochecker.variables,
1865            "Use the &brandShortname; instance.",
1866            "Gebruik die &brandShortname; weergawe.",
1867        )
1868        assert fails_serious(
1869            ooochecker.variables,
1870            "Use the &brandShortname; instance.",
1871            "Gebruik die &brandKortnaam; weergawe.",
1872        )
1873        assert passes(ooochecker.variables, "Save %file%", "Stoor %file%")
1874        assert fails_serious(ooochecker.variables, "Save %file%", "Stoor %leer%")
1875        assert passes(ooochecker.variables, "Save %file", "Stoor %file")
1876        assert fails_serious(ooochecker.variables, "Save %file", "Stoor %leer")
1877        assert passes(ooochecker.variables, "Save %1", "Stoor %1")
1878        assert fails_serious(ooochecker.variables, "Save %1", "Stoor %2")
1879        assert passes(ooochecker.variables, "Save %", "Stoor %")
1880        assert fails_serious(ooochecker.variables, "Save %", "Stoor")
1881        assert passes(ooochecker.variables, "Save $(file)", "Stoor $(file)")
1882        assert fails_serious(ooochecker.variables, "Save $(file)", "Stoor $(leer)")
1883        assert passes(ooochecker.variables, "Save $file$", "Stoor $file$")
1884        assert fails_serious(ooochecker.variables, "Save $file$", "Stoor $leer$")
1885        assert passes(ooochecker.variables, "Save ${file}", "Stoor ${file}")
1886        assert fails_serious(ooochecker.variables, "Save ${file}", "Stoor ${leer}")
1887        assert passes(ooochecker.variables, "Save #file#", "Stoor #file#")
1888        assert fails_serious(ooochecker.variables, "Save #file#", "Stoor #leer#")
1889        assert passes(ooochecker.variables, "Save #1", "Stoor #1")
1890        assert fails_serious(ooochecker.variables, "Save #1", "Stoor #2")
1891        assert passes(ooochecker.variables, "Save #", "Stoor #")
1892        assert fails_serious(ooochecker.variables, "Save #", "Stoor")
1893        assert passes(ooochecker.variables, "Save ($file)", "Stoor ($file)")
1894        assert fails_serious(ooochecker.variables, "Save ($file)", "Stoor ($leer)")
1895        assert passes(ooochecker.variables, "Save $[file]", "Stoor $[file]")
1896        assert fails_serious(ooochecker.variables, "Save $[file]", "Stoor $[leer]")
1897        assert passes(ooochecker.variables, "Save [file]", "Stoor [file]")
1898        assert fails_serious(ooochecker.variables, "Save [file]", "Stoor [leer]")
1899        assert passes(ooochecker.variables, "Save $file", "Stoor $file")
1900        assert fails_serious(ooochecker.variables, "Save $file", "Stoor $leer")
1901        assert passes(ooochecker.variables, "Use @EXTENSION@", "Gebruik @EXTENSION@")
1902        assert fails_serious(
1903            ooochecker.variables, "Use @EXTENSUION@", "Gebruik @UITBRUIDING@"
1904        )
1905        # Same variable name twice
1906        assert fails_serious(
1907            ooochecker.variables,
1908            r"""Start %PROGRAMNAME% as %PROGRAMNAME%""",
1909            "Begin %PROGRAMNAME%",
1910        )
1911
1912
1913def test_variables_cclicense():
1914    """Tests variables in Creative Commons translations."""
1915    checker = checks.CCLicenseChecker()
1916    assert passes(checker.variables, "CC-GNU @license_code@.", "CC-GNU @license_code@.")
1917    assert fails_serious(
1918        checker.variables, "CC-GNU @license_code@.", "CC-GNU @lisensie_kode@."
1919    )
1920    assert passes(
1921        checker.variables,
1922        "Deed to the @license_name_full@",
1923        "Akte vir die @license_name_full@",
1924    )
1925    assert fails_serious(
1926        checker.variables,
1927        "Deed to the @license_name_full@",
1928        "Akte vir die @volle_lisensie@",
1929    )
1930    assert passes(
1931        checker.variables, "The @license_name_full@ is", "Die @license_name_full@ is"
1932    )
1933    assert fails_serious(
1934        checker.variables, "The @license_name_full@ is", "Die @iiilicense_name_full@ is"
1935    )
1936    assert fails_serious(checker.variables, "A @ccvar@", "'n @ccvertaaldeveranderlike@")
1937
1938
1939def test_variables_ios():
1940    """Test variables in iOS translations"""
1941    ioschecker = checks.IOSChecker()
1942    assert passes(ioschecker.variables, "Welcome $(NAME)", "Welkom $(NAME)")
1943    assert fails_serious(ioschecker.variables, "Welcome $(NAME)", "Welkom $(NAAM)")
1944    assert fails_serious(ioschecker.variables, "Welcome $(NAME)", "Welkom")
1945
1946    assert passes(ioschecker.variables, "Welcome %@", "Welkom %@")
1947    assert fails_serious(ioschecker.variables, "Welcome %@", "Welkom $@")
1948    assert fails_serious(ioschecker.variables, "Welcome %@", "Welkom")
1949    assert passes(
1950        ioschecker.variables,
1951        "Downloading %1$@ at %2$@ speed",
1952        "Downloading at %2$@ speed the file %$1@",
1953    )
1954
1955
1956def test_xmltags():
1957    """tests xml tags"""
1958    stdchecker = checks.StandardChecker()
1959    assert fails(stdchecker.xmltags, "Do it <b>now</b>", "Doen dit <v>nou</v>")
1960    assert passes(stdchecker.xmltags, "Do it <b>now</b>", "Doen dit <b>nou</b>")
1961    assert passes(
1962        stdchecker.xmltags,
1963        'Click <img src="img.jpg">here</img>',
1964        'Klik <img src="img.jpg">hier</img>',
1965    )
1966    assert fails(
1967        stdchecker.xmltags,
1968        'Click <img src="image.jpg">here</img>',
1969        'Klik <img src="prent.jpg">hier</img>',
1970    )
1971    assert passes(
1972        stdchecker.xmltags,
1973        'Click <img src="img.jpg" alt="picture">here</img>',
1974        'Klik <img src="img.jpg" alt="prentjie">hier</img>',
1975    )
1976    assert passes(
1977        stdchecker.xmltags,
1978        'Click <a title="tip">here</a>',
1979        'Klik <a title="wenk">hier</a>',
1980    )
1981    assert passes(
1982        stdchecker.xmltags,
1983        'Click <div title="tip">here</div>',
1984        'Klik <div title="wenk">hier</div>',
1985    )
1986    assert passes(
1987        stdchecker.xmltags,
1988        "Start with the &lt;start&gt; tag",
1989        "Begin met die &lt;begin&gt;",
1990    )
1991
1992    assert fails(
1993        stdchecker.xmltags,
1994        'Click <a href="page.html">',
1995        'Klik <a hverw="page.html">',
1996    )
1997    assert passes(
1998        stdchecker.xmltags,
1999        'Click <a xml-lang="en" href="page.html">',
2000        'Klik <a xml-lang="af" href="page.html">',
2001    )
2002    assert passes(
2003        stdchecker.xmltags,
2004        'Click <div lang="en" dir="ltr">',
2005        'Klik <div lang="ar" dir="rtl">',
2006    )
2007    assert fails(
2008        stdchecker.xmltags,
2009        'Click <a href="page.html" target="koei">',
2010        'Klik <a href="page.html">',
2011    )
2012    assert fails(
2013        stdchecker.xmltags, "<b>Current Translation</b>", "<b>Traducción Actual:<b>"
2014    )
2015    assert passes(stdchecker.xmltags, "<Error>", "<Fout>")
2016    assert fails(
2017        stdchecker.xmltags,
2018        "%d/%d translated\n(%d blank, %d fuzzy)",
2019        "<br>%d/%d μεταφρασμένα\n<br>(%d κενά, %d ασαφή)",
2020    )
2021    assert fails(
2022        stdchecker.xmltags,
2023        '(and <a href="http://www.schoolforge.net/education-software" class="external">other open source software</a>)',
2024        '(en <a href="http://www.schoolforge.net/education-software" class="external">ander Vry Sagteware</a)',
2025    )
2026    assert fails(
2027        stdchecker.xmltags,
2028        'Because Tux Paint (and <a href="http://www.schoolforge.net/education-software" class="external">other open source software</a>) is free of cost and not limited in any way, a school can use it <i>today</i>, without waiting for procurement or a budget!',
2029        'Omdat Tux Paint (en <a href="http://www.schoolforge.net/education-software" class="external">ander Vry Sagteware</a)gratis is en nie beperk is op enige manier nie, kan \'n skool dit vandag</i> gebruik sonder om te wag vir goedkeuring of \'n begroting!',
2030    )
2031    assert fails(stdchecker.xmltags, "test <br />", "test <br>")
2032    assert fails(
2033        stdchecker.xmltags, "test <img src='foo.jpg'/ >", "test <img src='foo.jpg'  >"
2034    )
2035
2036    # This used to cause an error (traceback), because of mismatch between
2037    # different regular expressions (because of the newlines)
2038    assert passes(
2039        stdchecker.xmltags,
2040        """<markup>
2041<span weight="bold" size="large"
2042style="oblique">
2043Can't create server !
2044</span>
2045</markup>""",
2046        """<markup>
2047<span weight="bold" size="large"
2048style="oblique">
2049No s'ha pogut crear el servidor
2050</span>
2051</markup>""",
2052    )
2053    frchecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="fr"))
2054    assert fails(
2055        frchecker.xmltags, 'Click <a href="page.html">', "Klik <a href=« page.html »>"
2056    )
2057
2058
2059@mark.xfail(reason="Bug #3506")
2060def test_bengali_mozilla_inverted_xmltags():
2061    """Test Bengali Mozilla XML tags."""
2062    bn_mozilla_checker = checks.MozillaChecker(
2063        checkerconfig=checks.CheckerConfig(targetlanguage="bn")
2064    )
2065    str_en = """We <a href="%(cofound_url)s" rel="external">co-founded</a> the <a href="%(whatwg_url)s" rel="external">WHAT-WG</a> to."""
2066    str_bn = """এর প্রচলন ঘটাতে আমরা <a href="%(whatwg_url)s" rel="external">WHAT-WG</a> প্রতিষ্ঠায় <a href="%(cofound_url)s" rel="external">সহযোগী</a> ছিলাম।ন।"""
2067    assert passes(bn_mozilla_checker.xmltags, str_en, str_bn)
2068
2069
2070def test_ooxmltags():
2071    """Tests the xml tags in OpenOffice.org translations for quality as done in gsicheck"""
2072    for ooochecker in (checks.OpenOfficeChecker(), checks.LibreOfficeChecker()):
2073        # some attributes can be changed or removed
2074        assert fails(
2075            ooochecker.xmltags,
2076            '<img src="a.jpg" width="400">',
2077            '<img src="b.jpg" width="500">',
2078        )
2079        assert passes(
2080            ooochecker.xmltags,
2081            '<img src="a.jpg" width="400">',
2082            '<img src="a.jpg" width="500">',
2083        )
2084        assert passes(
2085            ooochecker.xmltags,
2086            '<img src="a.jpg" width="400">',
2087            '<img src="a.jpg">',
2088        )
2089        assert passes(
2090            ooochecker.xmltags,
2091            '<img src="a.jpg">',
2092            '<img src="a.jpg" width="400">',
2093        )
2094        assert passes(
2095            ooochecker.xmltags, '<alt xml-lang="ab">text</alt>', "<alt>teks</alt>"
2096        )
2097        assert passes(
2098            ooochecker.xmltags,
2099            '<ahelp visibility="visible">bla</ahelp>',
2100            "<ahelp>blu</ahelp>",
2101        )
2102        assert fails(
2103            ooochecker.xmltags,
2104            '<ahelp visibility="visible">bla</ahelp>',
2105            '<ahelp visibility="invisible">blu</ahelp>',
2106        )
2107        assert fails(
2108            ooochecker.xmltags,
2109            '<ahelp visibility="invisible">bla</ahelp>',
2110            "<ahelp>blu</ahelp>",
2111        )
2112        # some attributes can be changed, but not removed
2113        assert passes(ooochecker.xmltags, '<link name="John">', '<link name="Jan">')
2114        assert fails(ooochecker.xmltags, '<link name="John">', '<link naam="Jan">')
2115
2116        # Reported OOo error
2117        ## Bug 1910
2118        assert fails(
2119            ooochecker.xmltags,
2120            """<variable id="FehlendesElement">In a database file window, click the <emph>Queries</emph> icon, then choose <emph>Edit - Edit</emph>. When referenced fields no longer exist, you see this dialog</variable>""",
2121            """<variable id="FehlendesElement">Dans  une fenêtre de fichier de base de données, cliquez sur l'icône <emph>Requêtes</emph>, puis choisissez <emph>Éditer - Éditer</emp>. Lorsque les champs de référence n'existent plus, vous voyez cette boîte de dialogue</variable>""",
2122        )
2123        assert fails(
2124            ooochecker.xmltags,
2125            "<variable> <emph></emph> <emph></emph> </variable>",
2126            "<variable> <emph></emph> <emph></emp> </variable>",
2127        )
2128
2129
2130def test_functions():
2131    """tests to see that funtions() are not translated"""
2132    stdchecker = checks.StandardChecker()
2133    assert fails(stdchecker.functions, "blah rgb() blah", "blee brg() blee")
2134    assert passes(stdchecker.functions, "blah rgb() blah", "blee rgb() blee")
2135    assert fails(stdchecker.functions, "percentage in rgb()", "phesenthe kha brg()")
2136    assert passes(stdchecker.functions, "percentage in rgb()", "phesenthe kha rgb()")
2137    assert fails(stdchecker.functions, "rgb() in percentage", "brg() kha phesenthe")
2138    assert passes(stdchecker.functions, "rgb() in percentage", "rgb() kha phesenthe")
2139    assert fails(
2140        stdchecker.functions, "blah string.rgb() blah", "blee bleeb.rgb() blee"
2141    )
2142    assert passes(
2143        stdchecker.functions, "blah string.rgb() blah", "blee string.rgb() blee"
2144    )
2145    assert passes(stdchecker.functions, "or domain().", "domain() verwag.")
2146    assert passes(
2147        stdchecker.functions,
2148        "Expected url(), url-prefix(), or domain().",
2149        "url(), url-prefix() of domain() verwag.",
2150    )
2151
2152
2153def test_emails():
2154    """tests to see that email addresses are not translated"""
2155    stdchecker = checks.StandardChecker()
2156    assert fails(
2157        stdchecker.emails, "blah bob@example.net blah", "blee kobus@voorbeeld.net blee"
2158    )
2159    assert passes(
2160        stdchecker.emails, "blah bob@example.net blah", "blee bob@example.net blee"
2161    )
2162
2163
2164def test_urls():
2165    """tests to see that URLs are not translated"""
2166    stdchecker = checks.StandardChecker()
2167    assert fails(
2168        stdchecker.urls,
2169        "blah http://translate.org.za blah",
2170        "blee http://vertaal.org.za blee",
2171    )
2172    assert passes(
2173        stdchecker.urls,
2174        "blah http://translate.org.za blah",
2175        "blee http://translate.org.za blee",
2176    )
2177
2178
2179def test_simpleplurals():
2180    """test that we can find English style plural(s)"""
2181    stdchecker = checks.StandardChecker()
2182    assert passes(stdchecker.simpleplurals, "computer(s)", "rekenaar(s)")
2183    assert fails(stdchecker.simpleplurals, "plural(s)", "meervoud(e)")
2184    assert fails(
2185        stdchecker.simpleplurals,
2186        "Ungroup Metafile(s)...",
2187        "Kuvhanganyululani Metafaela(dzi)...",
2188    )
2189
2190    # Test a language that doesn't use plurals
2191    stdchecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="vi"))
2192    assert passes(stdchecker.simpleplurals, "computer(s)", "Máy tính")
2193    assert fails(stdchecker.simpleplurals, "computer(s)", "Máy tính(s)")
2194
2195
2196def test_nplurals():
2197    """
2198    Test that we can find the wrong number of plural forms. Note that this
2199    test uses a UnitChecker, not a translation checker.
2200    """
2201    checker = checks.StandardUnitChecker()
2202    unit = po.pounit("")
2203
2204    unit.source = ["%d file", "%d files"]
2205    unit.target = ["%d lêer", "%d lêers"]
2206    assert checker.nplurals(unit)
2207
2208    checker = checks.StandardUnitChecker(checks.CheckerConfig(targetlanguage="af"))
2209    unit.source = "%d files"
2210    unit.target = "%d lêer"
2211    assert checker.nplurals(unit)
2212
2213    unit.source = ["%d file", "%d files"]
2214    unit.target = ["%d lêer", "%d lêers"]
2215    assert checker.nplurals(unit)
2216
2217    unit.source = ["%d file", "%d files"]
2218    unit.target = ["%d lêer", "%d lêers", "%d lêeeeers"]
2219    assert not checker.nplurals(unit)
2220
2221    unit.source = ["%d file", "%d files"]
2222    unit.target = ["%d lêer"]
2223    assert not checker.nplurals(unit)
2224
2225    checker = checks.StandardUnitChecker(checks.CheckerConfig(targetlanguage="km"))
2226    unit.source = "%d files"
2227    unit.target = "%d ឯកសារ"
2228    assert checker.nplurals(unit)
2229
2230    unit.source = ["%d file", "%d files"]
2231    unit.target = ["%d ឯកសារ"]
2232    assert checker.nplurals(unit)
2233
2234    unit.source = ["%d file", "%d files"]
2235    unit.target = ["%d ឯកសារ", "%d lêers"]
2236    assert not checker.nplurals(unit)
2237
2238
2239def test_credits():
2240    """tests credits"""
2241    stdchecker = checks.StandardChecker()
2242    assert passes(stdchecker.credits, "File", "iFayile")
2243    assert passes(stdchecker.credits, "&File", "&Fayile")
2244    assert passes(stdchecker.credits, "translator-credits", "Ekke, ekke!")
2245    assert passes(stdchecker.credits, "Your names", "Ekke, ekke!")
2246    assert passes(stdchecker.credits, "ROLES_OF_TRANSLATORS", "Ekke, ekke!")
2247    kdechecker = checks.KdeChecker()
2248    assert passes(kdechecker.credits, "File", "iFayile")
2249    assert passes(kdechecker.credits, "&File", "&Fayile")
2250    assert passes(kdechecker.credits, "translator-credits", "Ekke, ekke!")
2251    assert fails(kdechecker.credits, "Your names", "Ekke, ekke!")
2252    assert fails(kdechecker.credits, "ROLES_OF_TRANSLATORS", "Ekke, ekke!")
2253    gnomechecker = checks.GnomeChecker()
2254    assert passes(gnomechecker.credits, "File", "iFayile")
2255    assert passes(gnomechecker.credits, "&File", "&Fayile")
2256    assert fails(gnomechecker.credits, "translator-credits", "Ekke, ekke!")
2257    assert passes(gnomechecker.credits, "Your names", "Ekke, ekke!")
2258    assert passes(gnomechecker.credits, "ROLES_OF_TRANSLATORS", "Ekke, ekke!")
2259
2260
2261def test_gconf():
2262    """test GNOME gconf errors"""
2263    gnomechecker = checks.GnomeChecker()
2264    # Let's cheat a bit and prepare the checker as the run_filters() method
2265    # would do by adding locations needed by the gconf test
2266    gnomechecker.locations = []
2267    assert passes(gnomechecker.gconf, 'Blah "gconf_setting"', 'Bleh "gconf_setting"')
2268    assert passes(gnomechecker.gconf, 'Blah "gconf_setting"', 'Bleh "gconf_steling"')
2269    gnomechecker.locations = ["file.schemas.in.h:24"]
2270    assert passes(gnomechecker.gconf, 'Blah "gconf_setting"', 'Bleh "gconf_setting"')
2271    assert fails(gnomechecker.gconf, 'Blah "gconf_setting"', 'Bleh "gconf_steling"')
2272    # redo the same, but with the new location comment:
2273    gnomechecker.locations = ["file.gschema.xml.in.in.h:24"]
2274    assert passes(gnomechecker.gconf, 'Blah "gconf_setting"', 'Bleh "gconf_setting"')
2275    assert fails(gnomechecker.gconf, 'Blah "gconf_setting"', 'Bleh "gconf_steling"')
2276
2277
2278def test_validxml():
2279    """test wheather validxml recognize invalid xml/html expressions"""
2280    lochecker = checks.LibreOfficeChecker()
2281    # Test validity only for xrm and xhp files
2282    lochecker.locations = ["description.xml"]
2283    assert passes(lochecker.validxml, "", "normal string")
2284    assert passes(lochecker.validxml, "", "<emph> only an open tag")
2285    lochecker.locations = ["readme.xrm"]
2286    assert passes(lochecker.validxml, "", "normal string")
2287    assert passes(lochecker.validxml, "", "<tt>closed formula</tt>")
2288    assert fails(lochecker.validxml, "", "<tt> only an open tag")
2289    lochecker.locations = ["wikisend.xhp"]
2290    assert passes(lochecker.validxml, "", "A <emph> well formed expression </emph>")
2291    assert fails(lochecker.validxml, "", "Missing <emph> close tag <emph>")
2292    assert fails(lochecker.validxml, "", "Missing open tag </emph>")
2293    assert fails(lochecker.validxml, "", "<emph/> is not a valid self-closing tag")
2294    assert fails(
2295        lochecker.validxml,
2296        "",
2297        '<ahelp hid="."> open tag not match with close tag</link>',
2298    )
2299    assert passes(
2300        lochecker.validxml,
2301        "",
2302        "Skip <IMG> because it is with capitalization so it is part of the text",
2303    )
2304    assert passes(
2305        lochecker.validxml,
2306        "",
2307        "Skip the capitalized <Empty>, because it is just a pseudo tag not a real one",
2308    )
2309    assert passes(
2310        lochecker.validxml, "", "Skip <br/> short tag, because no need to close it."
2311    )
2312    assert fails(
2313        lochecker.validxml, "", "<br></br> invalid, since should be self-closing tag"
2314    )
2315    # Larger tests
2316    assert passes(
2317        lochecker.validxml,
2318        "",
2319        "<bookmark_value>yazdırma; çizim varsayılanları</bookmark_value><bookmark_value>çizimler; yazdırma varsayılanları</bookmark_value><bookmark_value>sayfalar;sunumlarda sayfa adı yazdırma</bookmark_value><bookmark_value>yazdırma; sunumlarda tarihler</bookmark_value><bookmark_value>tarihler; sunumlarda  yazdırma</bookmark_value><bookmark_value>zamanlar; sunumları yazdırırken ekleme</bookmark_value><bookmark_value>yazdırma; sunumların gizli sayfaları</bookmark_value><bookmark_value>gizli sayfalar; sunumlarda yazdırma</bookmark_value><bookmark_value>yazdırma; sunumlarda ölçeklendirme olmadan</bookmark_value><bookmark_value>ölçekleme; sunumlar yazdırılırken</bookmark_value><bookmark_value>yazdırma; sunumlarda sayfalara sığdırma</bookmark_value><bookmark_value>sayfalara sığdırma; sunumlarda yazdırma ayarları</bookmark_value><bookmark_value>yazdırma; sunumlarda kapak sayfası</bookmark_value>",
2320    )
2321    # self-closing tag amongst other tag is valid
2322    assert passes(
2323        lochecker.validxml,
2324        "",
2325        '<link href="text/scalc/01/04060184.xhp#average">MITTELWERT</link>, <link href="text/scalc/01/04060184.xhp#averagea">MITTELWERTA</link>, <embedvar href="text/scalc/01/func_averageifs.xhp#averageifs_head"/>, <link href="text/scalc/01/04060184.xhp#max">MAX</link>, <link href="text/scalc/01/04060184.xhp#min">MIN</link>, <link href="text/scalc/01/04060183.xhp#large">KGRÖSSTE</link>, <link href="text/scalc/01/04060183.xhp#small">KKLEINSTE</link>',
2326    )
2327    assert fails(
2328        lochecker.validxml,
2329        "",
2330        'Kullanıcı etkileşimi verisinin kaydedilmesini ve bu verilerin gönderilmesini dilediğiniz zaman etkinleştirebilir veya devre dışı bırakabilirsiniz.  <item type="menuitem"><switchinline select="sys"><caseinline select="MAC">%PRODUCTNAME - Tercihler</caseinline><defaultinline>Araçlar - Seçenekler</defaultinline></switchinline> - %PRODUCTNAME - Gelişim Programı</item>\'nı seçin. Daha fazla bilgi için web sitesinde gezinmek için <defaultinline>Bilgi</emph> simgesine tıklayın.',
2331    )
2332    assert fails(
2333        lochecker.validxml,
2334        "",
2335        '<caseinline select="DRAW">Bir sayfanın içerik menüsünde ek komutlar vardır:</caseinline><caseinline select="IMPRESS">Bir sayfanın içerik menüsünde ek komutlar vardır:</caseinline></switchinline>',
2336    )
2337    assert fails(
2338        lochecker.validxml,
2339        "",
2340        "<bookmark_value>sunum; sihirbazı başlatmak<bookmark_value>nesneler; her zaman taşınabilir (Impress/Draw)</bookmark_value><bookmark_value>çizimleri eğriltme</bookmark_value><bookmark_value>aralama; sunumdaki sekmeler</bookmark_value><bookmark_value>metin nesneleri; sunumlarda ve çizimlerde</bookmark_value>",
2341    )
2342
2343
2344def test_hassuggestion():
2345    """test that hassuggestion() works"""
2346    checker = checks.StandardUnitChecker()
2347
2348    po_store = po.pofile()
2349    po_store.addsourceunit("koeie")
2350    assert checker.hassuggestion(po_store.units[-1])
2351
2352    xliff_store = xliff.xlifffile.parsestring(
2353        """
2354<xliff version='1.2'
2355       xmlns='urn:oasis:names:tc:xliff:document:1.2'>
2356<file original='hello.txt' source-language='en' target-language='fr' datatype='plaintext'>
2357<body>
2358    <trans-unit id='hi'>
2359        <source>Hello world</source>
2360        <target>Bonjour le monde</target>
2361        <alt-trans>
2362            <target xml:lang='es'>Hola mundo</target>
2363        </alt-trans>
2364    </trans-unit>
2365</body>
2366</file>
2367</xliff>
2368"""
2369    )
2370    assert not checker.hassuggestion(xliff_store.units[0])
2371
2372
2373def test_dialogsizes():
2374    """test Mozilla dialog sizes"""
2375    mozillachecker = checks.MozillaChecker()
2376    assert passes(mozillachecker.dialogsizes, "width: 12em;", "width: 12em;")
2377    assert passes(
2378        mozillachecker.dialogsizes,
2379        "width: 12em; height: 36em",
2380        "width: 12em; height: 36em",
2381    )
2382    assert fails(mozillachecker.dialogsizes, "height: 12em;", "hoogde: 12em;")
2383    assert passes(mozillachecker.dialogsizes, "height: 12em;", "height: 24px;")
2384    assert fails(mozillachecker.dialogsizes, "height: 12em;", "height: 24xx;")
2385    assert fails(mozillachecker.dialogsizes, "height: 12.5em;", "height: 12,5em;")
2386    assert fails(
2387        mozillachecker.dialogsizes,
2388        "width: 36em; height: 18em;",
2389        "width: 30em; min-height: 20em;",
2390    )
2391
2392
2393def test_skip_checks_per_language_in_some_checkers():
2394    """Test some checks are skipped for some languages in Mozilla checker."""
2395    from translate.storage import base
2396
2397    # Hijack checker config language ignoretests to test check is skipped.
2398    checker_config = checks.CheckerConfig(targetlanguage="gl")
2399    previous_ignoretests = checker_config.lang.ignoretests
2400    checker_config.lang.ignoretests = {
2401        "mozilla": ["accelerators"],
2402    }
2403
2404    # Prepare the checkers and the unit.
2405    mozillachecker = checks.MozillaChecker(checkerconfig=checker_config)
2406    stdchecker = checks.StandardChecker(
2407        checkerconfig=checks.CheckerConfig(accelmarkers="&", targetlanguage="gl")
2408    )
2409
2410    str1, str2, __ = strprep("&Check for updates", "আপডেইটসমূহৰ বাবে নিৰীক্ষণ কৰক")
2411    unit = base.TranslationUnit(str1)
2412    unit.target = str2
2413
2414    # Accelerators check is disabled for this language in MozillaChecker.
2415    assert "accelerators" not in mozillachecker.run_filters(unit).keys()
2416
2417    # But it is not in StandardChecker.
2418    assert "accelerators" in stdchecker.run_filters(unit).keys()
2419
2420    # Undo hijack.
2421    checker_config.lang.ignoretests = previous_ignoretests
2422
2423
2424def test_mozilla_no_accelerators_for_indic():
2425    """
2426    Test accelerators in MozillaChecker fails if accelerator in target.
2427
2428    No-accelerators is a special behavior of accelerators check in some
2429    languages that is present in MozillaChecker.
2430    """
2431    mozillachecker = checks.MozillaChecker(
2432        checkerconfig=checks.CheckerConfig(targetlanguage="as")
2433    )
2434    assert fails(mozillachecker.accelerators, "&File", "&Fayile")
2435    assert fails(mozillachecker.accelerators, "My add&-ons", "&Byvoengs mit")
2436    assert passes(mozillachecker.accelerators, "&File", "Fayile")
2437    assert fails(mozillachecker.accelerators, "File", "&Fayile")
2438    assert passes(mozillachecker.accelerators, "Mail &amp; News", "Po en Nuus")
2439    assert fails(mozillachecker.accelerators, "Mail &amp; News", "Po en &Nuus")
2440    assert passes(mozillachecker.accelerators, "Mail & News", "Pos & Nuus")
2441
2442
2443def test_noaccelerators_only_in_mozilla_checker():
2444    """
2445    Test no-accelerators check is only present in Mozilla checker.
2446
2447    No-accelerators is a special behavior of accelerators check in some
2448    languages that is present in MozillaChecker.
2449    """
2450    from translate.storage import base
2451
2452    asmozillachecker = checks.MozillaChecker(
2453        checkerconfig=checks.CheckerConfig(targetlanguage="as")
2454    )
2455    glmozillachecker = checks.MozillaChecker(
2456        checkerconfig=checks.CheckerConfig(targetlanguage="gl")
2457    )
2458    stdchecker = checks.StandardChecker(
2459        checkerconfig=checks.CheckerConfig(accelmarkers="&", targetlanguage="as")
2460    )
2461
2462    # Accelerators check passes for Assamesse in Mozilla checker. It fails for
2463    # Assamesse in Standard checker or for other languages in Mozilla Checker.
2464    str1, str2, __ = strprep("&Check for updates", "আপডেইটসমূহৰ বাবে নিৰীক্ষণ কৰক")
2465    unit = base.TranslationUnit(str1)
2466    unit.target = str2
2467
2468    gl_failures = glmozillachecker.run_filters(unit)
2469    std_failures = stdchecker.run_filters(unit)
2470
2471    assert "accelerators" not in asmozillachecker.run_filters(unit)
2472    assert "accelerators" in gl_failures
2473    assert "should not appear" not in gl_failures["accelerators"]
2474    assert "accelerators" in std_failures
2475    assert "should not appear" not in std_failures["accelerators"]
2476
2477    # Accelerators check passes. The ampersand should be detected as part of
2478    # a variable.
2479    str1, str2, __ = strprep("About &brandFullName;", "&brandFullName; ৰ বিষয়ে")
2480    unit = base.TranslationUnit(str1)
2481    unit.target = str2
2482
2483    assert "accelerators" not in asmozillachecker.run_filters(unit)
2484    assert "accelerators" not in glmozillachecker.run_filters(unit)
2485    assert "accelerators" not in stdchecker.run_filters(unit)
2486
2487    # Accelerators check fails for Assamesse in Mozilla checker since the
2488    # accelerator is present in the target. It passes for other languages or
2489    # other checkers.
2490    str1, str2, __ = strprep("&Cancel", "বাতিল কৰক (&C)")
2491    unit = base.TranslationUnit(str1)
2492    unit.target = str2
2493
2494    as_failures = asmozillachecker.run_filters(unit)
2495
2496    assert asmozillachecker.config.language_script == "assamese"
2497    assert "accelerators" in as_failures
2498    assert "should not appear" in as_failures["accelerators"]
2499    assert "accelerators" not in glmozillachecker.run_filters(unit)
2500    assert "accelerators" not in stdchecker.run_filters(unit)
2501
2502
2503def test_ensure_accelerators_not_in_target_if_not_in_source():
2504    """Test accelerators check works different for some languages in Mozilla."""
2505    from translate.storage import base
2506
2507    af_mozilla_checker = checks.MozillaChecker(
2508        checkerconfig=checks.CheckerConfig(targetlanguage="af")
2509    )
2510    km_mozilla_checker = checks.MozillaChecker(
2511        checkerconfig=checks.CheckerConfig(targetlanguage="km")
2512    )
2513
2514    # Afrikaans passes: Correct use of accesskeys.
2515    # Khmer fails: Translation shouldn't have an accesskey.
2516    src, tgt, __ = strprep("&One", "&Een")
2517    unit = base.TranslationUnit(src)
2518    unit.target = tgt
2519
2520    km_failures = km_mozilla_checker.run_filters(unit)
2521
2522    assert "accelerators" not in af_mozilla_checker.run_filters(unit)
2523    assert "accelerators" in km_failures
2524    assert "should not appear" in km_failures["accelerators"]
2525
2526    # Afrikaans fails: Translation is missing the accesskey.
2527    # Khmer passes: Translation doesn't need accesskey for this language.
2528    src, tgt, __ = strprep("&Two", "Twee")
2529    unit = base.TranslationUnit(src)
2530    unit.target = tgt
2531
2532    af_failures = af_mozilla_checker.run_filters(unit)
2533
2534    assert "accelerators" in af_failures
2535    assert "Missing accelerator" in af_failures["accelerators"]
2536    assert "accelerators" not in km_mozilla_checker.run_filters(unit)
2537
2538    # Afrikaans fails: No accesskey in the source, but yes on translation.
2539    # Khmer fails: Translation doesn't need accesskey, but it has accesskey.
2540    src, tgt, __ = strprep("Three", "&Drie")
2541    unit = base.TranslationUnit(src)
2542    unit.target = tgt
2543
2544    af_failures = af_mozilla_checker.run_filters(unit)
2545    km_failures = km_mozilla_checker.run_filters(unit)
2546
2547    assert "accelerators" in af_failures
2548    assert "Added accelerator" in af_failures["accelerators"]
2549    assert "accelerators" in km_failures
2550    assert "should not appear" in km_failures["accelerators"]
2551
2552
2553def test_ensure_bengali_languages_script_is_correct():
2554    """Test script for Bengali languages is correctly set."""
2555    bn_BD_mozilla_checker = checks.MozillaChecker(
2556        checkerconfig=checks.CheckerConfig(targetlanguage="bn_BD")
2557    )
2558    bn_IN_mozilla_checker = checks.MozillaChecker(
2559        checkerconfig=checks.CheckerConfig(targetlanguage="bn_IN")
2560    )
2561    bn_mozilla_checker = checks.MozillaChecker(
2562        checkerconfig=checks.CheckerConfig(targetlanguage="bn_IN")
2563    )
2564    assert bn_BD_mozilla_checker.config.language_script == "Beng"
2565    assert bn_IN_mozilla_checker.config.language_script == "Beng"
2566    assert bn_mozilla_checker.config.language_script == "Beng"
2567
2568
2569def test_category():
2570    """Tests checker categories aren't mixed up."""
2571    from translate.storage import base
2572
2573    unit = base.TranslationUnit("foo")
2574    unit.target = "bar"
2575
2576    standard_checker = checks.StandardChecker()
2577    assert standard_checker.categories == {}
2578    standard_checker.run_filters(unit)
2579    assert standard_checker.categories != {}
2580    assert "validxml" not in standard_checker.categories.keys()
2581    standard_categories_count = len(standard_checker.categories.values())
2582
2583    libo_checker = checks.LibreOfficeChecker()
2584    assert libo_checker.categories == {}
2585    libo_checker.run_filters(unit)
2586    assert libo_checker.categories != {}
2587    assert "validxml" in libo_checker.categories.keys()
2588
2589    standard_checker = checks.StandardChecker()
2590    assert standard_checker.categories == {}
2591    standard_checker.run_filters(unit)
2592    assert standard_checker.categories != {}
2593    assert len(standard_checker.categories.values()) == standard_categories_count
2594    assert "validxml" not in standard_checker.categories.keys()
2595