grammar checker (which Office calls a proof reader).
We’ll look at how to program using the spell checker, thesaurus, and two grammar checkers, but skip the hyphenator which is easier to use interactively through Office’s GUI.
We’ll describe two examples, Lingo and Lingo File.
The first lists information about the linguistic services, then uses the spell checker, thesaurus, and grammar checker ‘standalone’ without having to load an Office document first.
Lingo File automatically spell checks and grammar checks a complete file, reporting errors without altering the document.
One topic I’ll be ignoring is how to create and edit the data files used by the linguistic services.
For that task, you should have a look at PTG (Proofing Tool GUI) developed by Marco Pinto at https://www.proofingtoolgui.org/.
It’s an open source tool for editing Office’s dictionary, thesaurus, hyphenation, and autocorrect files.
Another area that is skipped here is the use of events and listeners.
Please refer to the “Linguistics” sub-section of chapter 6 of the Developer’s Guide for details (loguideLinguistics).
Listener code can be found in LinguisticExample.java mentioned above.
Also see Chapter 4. Listening, and Other Techniques.
The linguistic features accessible through Office’s GUI are explained in chapter 3 of the “Writer Guide”, available at https://libreoffice.org/get-help/documentation,
starting from the section called “Checking spelling and grammar”.
An older information source is the LingucomponentProject page at the OpenOffice website,
https://openoffice.org/lingucomponent, which links to some useful tools, such as alternative grammar checkers.
An interesting set of slides by Daniel Naber explaining the state of the project in 2005 can be found at http://danielnaber.de/publications/, along with more recent material.
Lingo example prints a variety of information about the linguistics services:
defmain()->int:withLo.Loader(Lo.ConnectSocket(headless=True))asloader:# print linguistics infoWrite.dicts_info()lingu_props=Write.get_lingu_properties()Props.show_props("Linguistic Manager",lingu_props)Info.list_extensions()# these include linguistic extensionslingo_mgr=Lo.create_instance_mcf(XLinguServiceManager2,"com.sun.star.linguistic2.LinguServiceManager")iflingo_mgrisNone:print("No linguistics manager found")return0Write.print_services_info(lingo_mgr)# : code for using the services; see later
Each line includes the name of a dictionary, its number of entries, whether it’s active (i.e. being used), its locale, and whether it’s a positive, negative, or mixed dictionary.
A positive dictionary holds correctly spelled words only, while a negative one lists incorrectly spelled words.
A mixed dictionary contains both correctly and incorrectly spelled entries.
If a dictionary has a locale, such as “GB” for en-GB.dic, then it’s only utilized during spell checking if its locale matches Office’s.
The Office locale can be set via the Tools, Options, Language Settings, “Languages” dialog shown in Fig. 72.
# in the Write class@classmethoddefdicts_info(cls)->None:dict_lst=Lo.create_instance_mcf(XSearchableDictionaryList,"com.sun.star.linguistic2.DictionaryList")ifnotdict_lst:print("No list of dictionaries found")returncls.print_dicts_info(dict_lst)cd_list=mLo.Lo.create_instance_mcf(XConversionDictionaryList,"com.sun.star.linguistic2.ConversionDictionaryList")ifcd_listisNone:print("No list of conversion dictionaries found")returncls.print_con_dicts_info(cd_list)
It retrieves a conventional dictionary list first (called dict_lst), and iterates through its dictionaries using print_con_dicts_info().
Then it obtains the conversion dictionary list (called cd_list), and iterates over that with print_con_dicts_info().
Fig. 73 shows the main services and interfaces used by ordinary dictionaries.
Each dictionary in the list has an XDictionary interface which contains methods for accessing and changing its entries.
print_dicts_info() retrieves an XDictionary sequence from the list, and prints out a summary of each dictionary:
# in the Write class@classmethoddefprint_dicts_info(cls,dict_list:XSearchableDictionaryList)->None:ifdict_listisNone:print("Dictionary list is null")returnprint(f"No. of dictionaries: {dict_list.getCount()}")dicts=dict_list.getDictionaries()fordindicts:ch10fig_convert_dicts_servicesprint(f" {d.getName()} ({d.getCount()}); ({'active'ifd.isActive()else'na'}); '{d.getLocale().Country}'; {cls.get_dict_type(d.getDictionaryType())}")print()@staticmethoddefget_dict_type(dt:Write.DictionaryType)->str:ifdt==Write.DictionaryType.POSITIVE:return"positive"ifdt==Write.DictionaryType.NEGATIVE:return"negative"ifdt==Write.DictionaryType.MIXED:return"mixed"return"??"
Conversion dictionaries map words in one language/dialect to corresponding words in another language/dialect.
Fig. 74 shows that conversion dictionaries are organized in a similar way to ordinary ones.
The interfaces for manipulating a conversion dictionary are XConversionDictionary and XConversionPropertyType.
# in the Write class@staticmethoddefprint_con_dicts_info(cd_lst:XConversionDictionaryList)->None:ifcd_lstisNone:print("Conversion Dictionary list is null")returndc_con=cd_lst.getDictionaryContainer()dc_names=dc_con.getElementNames()print(f"No. of conversion dictionaries: {len(dc_names)}")fornameindc_names:print(f" {name}")print()
Output similar to Write.dicts_info() can be viewed via Office’s Tools, Options, Language Settings, “Writing Aids” dialog, shown in Fig. 75.
The dictionaries are listed in the second pane of the dialog.
Also, at the bottom of the window is a “Get more dictionaries online” hyperlink which takes the user to Office’s extension website, and displays the “Dictionary” category (see Fig. 76).
Fig. 76 :The Dictionary Extensions at the LibreOffice Website.
These properties are explained in the online documentation for the XLinguProperties interface (lodocXLinguProperties), and also in the Developer’s Guide.
The properties are spread across several dialog in Office’s GUI, starting from the Tools, Options, “Language Settings” menu item.
However, most of them are in the “Options” pane of the “Writing Aids” Dialog in Fig. 75.
Additional dictionaries, and other language tools such as grammar checkers, are loaded into Office as extensions, so calling Info.list_extensions() can be informative.
# in the Info class@classmethoddeflist_extensions(cls)->None:try:pip=cls.get_pip()exceptMissingInterfaceError:print("No package info provider found")returnexts_tbl=pip.getExtensionList()print("\nExtensions:")foriinrange(len(exts_tbl)):print(f"{i+1}. ID: {exts_tbl[i][0]}")print(f" Version: {exts_tbl[i][1]}")print(f" Loc: {pip.getPackageLocation(exts_tbl[i][0])}")print()
The LinguServiceManager provides access to three of the four main linguistic services: the spell checker, the hyphenator, and thesaurus.
The proof reader (ex: the grammar checker) is managed by a separate Proofreader service, which is explained later.
Fig. 78 shows the interfaces accessible from the LinguServiceManager service.
# in lingo example# get lingo managerlingo_mgr=Lo.create_instance_mcf(XLinguServiceManager2,"com.sun.star.linguistic2.LinguServiceManager")iflingo_mgrisNone:print("No linguistics manager found")return0Write.print_services_info(lingo_mgr)
Available Services:
SpellChecker (1):
org.openoffice.lingu.MySpellSpellChecker
Thesaurus (1):
org.openoffice.lingu.new.Thesaurus
Hyphenator (1):
org.openoffice.lingu.LibHnjHyphenator
Proofreader (2):
org.languagetool.openoffice.Main
org.libreoffice.comp.pyuno.Lightproof.en
Configured Services:
SpellChecker (1):
org.openoffice.lingu.MySpellSpellChecker
Thesaurus (1):
org.openoffice.lingu.new.Thesaurus
Hyphenator (1):
org.openoffice.lingu.LibHnjHyphenator
Proofreader (1):
org.libreoffice.comp.pyuno.Lightproof.en
Locales for SpellChecker (46)
AR AU BE BO BS BZ CA CA CH CL
CO CR CU DO EC ES FR GB GH GQ
GT HN IE IN JM LU MC MW MX NA
NI NZ PA PE PH PH PR PY SV TT
US US UY VE ZA ZW
Locales for Thesaurus (46)
AR AU BE BO BS BZ CA CA CH CL
CO CR CU DO EC ES FR GB GH GQ
GT HN IE IN JM LU MC MW MX NA
NI NZ PA PE PH PH PR PY SV TT
US US UY VE ZA ZW
Locales for Hyphenator (46)
AR AU BE BO BS BZ CA CA CH CL
CO CR CU DO EC ES FR GB GH GQ
GT HN IE IN JM LU MC MW MX NA
NI NZ PA PE PH PH PR PY SV TT
US US UY VE ZA ZW
Locales for Proofreader (111)
AE AF AO AR AT AU BE BE BE BH
BO BR BS BY BZ CA CA CD CH CH
CH CI CL CM CN CR CU CV DE DE
DK DO DZ EC EG ES ES ES ES ES
FI FR FR GB GH GR GT GW HN HT
IE IE IN IN IQ IR IT JM JO JP
KH KW LB LI LU LU LY MA MA MC
ML MO MX MZ NA NI NL NZ OM PA
PE PH PH PL PR PT PY QA RE RO
RU SA SD SE SI SK SN ST SV SY
TL TN TT UA US US UY VE YE ZA
ZW
The print-out contains three lists: a list of available services, a list of configured services (i.e. ones that are activated inside Office),
and a list of the locales available to each service.
Fig. 78 shows that LinguServiceManager only manages the spell checker, hyphenator, and thesaurus, and yet Write.print_services_info()
includes information about the proof reader. Somewhat confusingly, although LinguServiceManager cannot instantiate a proof reader it can print information about it.
The output shows that two proofreader services are available (org.languagetool.openoffice.Main and org.libreoffice.comp.pyuno.Lightproof.en), but only one is configured (i.e. active).
This setup is explained when we talk about the proof reader later.
# in the Write class@classmethoddefprint_services_info(cls,lingo_mgr:XLinguServiceManager2,loc:Locale|None=None)->None:iflocisNone:loc=Locale("en","US","")print("Available Services:")cls.print_avail_service_info(lingo_mgr,"SpellChecker",loc)cls.print_avail_service_info(lingo_mgr,"Thesaurus",loc)cls.print_avail_service_info(lingo_mgr,"Hyphenator",loc)cls.print_avail_service_info(lingo_mgr,"Proofreader",loc)print()print("Configured Services:")cls.print_config_service_info(lingo_mgr,"SpellChecker",loc)cls.print_config_service_info(lingo_mgr,"Thesaurus",loc)cls.print_config_service_info(lingo_mgr,"Hyphenator",loc)cls.print_config_service_info(lingo_mgr,"Proofreader",loc)print()cls.print_locales("SpellChecker",lingo_mgr.getAvailableLocales("com.sun.star.linguistic2.SpellChecker"))cls.print_locales("Thesaurus",lingo_mgr.getAvailableLocales("com.sun.star.linguistic2.Thesaurus"))cls.print_locales("Hyphenator",lingo_mgr.getAvailableLocales("com.sun.star.linguistic2.Hyphenator"))cls.print_locales("Proofreader",lingo_mgr.getAvailableLocales("com.sun.star.linguistic2.Proofreader"))print()
The choice of services depends on the current locale by default, so Write.print_services_info() begins by creating an American English locale, which matches my version of Office.
Write.print_services_info() can also take a Locale as an option.
Write.print_avail_service_info() utilizes XLinguServiceManager.getAvailableServices() to retrieve a list of the available services.
In a similar way, Write.print_config_service_info() calls XLinguServiceManager.getConfiguredServices(),
and Write.print_locales() gets a sequence of Locale objects from XLinguServiceManager.getAvailableLocales().
There’s a few examples in Lingo example of applying the spell checker to individual words:
# in lingo example# use spell checkerWrite.spell_word("horseback",speller)Write.spell_word("ceurse",speller)Write.spell_word("magisian",speller)Write.spell_word("ellucidate",speller)
XLinguServiceManager.getSpellChecker() returns a reference to the spell checker, and Write.spell_word() checks the supplied word.
For the code above, the following is printed:
* "ceurse" is unknown. Try:
No. of names: 8
"curse" "course" "secateurs" "cerise"
"surcease" "secure" "cease" "Ceausescu"
* "magisian" is unknown. Try:
No. of names: 7
"magician" "magnesia" "Malaysian" "mismanage"
"imagining" "mastication" "fumigation"
* "ellucidate" is unknown. Try:
No. of names: 7
"elucidate" "elucidation" "hallucinate" "pellucid"
"fluoridate" "elasticated" "illustrated"
Nothing is reported for horseback because that’s correctly spelled, and spell_word() returns the boolean true.
Write.spell_word() utilizes XSpellChecker.spell() to find a spelling mistake, then prints the alternative spellings:
# in the Write class@staticmethoddefspell_word(word:str,speller:XSpellChecker,loc:Locale|None=None)->bool:iflocisNone:loc=Locale("en","US","")alts=speller.spell(word,loc,())ifaltsisnotNone:print(f"* '{word}' is unknown. Try:")alt_words=alts.getAlternatives()mLo.Lo.print_names(alt_words)returnFalsereturnTrue
XSpellChecker.spell() requires a tuple and an array of properties, which is left empty.
The properties are those associated with XLinguProperties, which were listed above using Write.get_lingu_properties().
Its output shows that IsSpellCapitalization is presently True, which means that words in all-caps will be checked.
The property can be changed to false inside the PropertyValue tuple passed to XSpellChecker.spell(). For example:
Now an incorrectly spelled word in all-caps, such as CEURSE will be skipped over.
This means that Write.spellWord("CEURSE",speller) should return True.
Unfortunately, XSpellChecker.spell() seems to ignore the property array, and still reports CEURSE as incorrectly spelled.
Even a property change performed through the XLinguProperties interface, such as:
fails to change XSpellChecker.spell()’s behavior.
The only way to make a change to the linguistic properties that is acted upon is through the “Options” pane in the “Writing Aids” dialog, as in Fig. 80.
Office’s default spell checker is Hunspell (from https://hunspell.github.io/), and has been part of OpenOffice since v.2, when it replaced
MySpell, adding several features such as support for Unicode. The MySpell name lives on in a few places, such as in the spelling service (org.openoffice.lingu.MySpellSpellChecker).
Hunspell offers extra properties in addition to those in the “Options” pane of the “Writing Aids” dialog.
They can be accessed through the Tools, Options, Language Settings, “English sentence checking” dialog shown in Fig. 81.
The same dialog can also be reached through the Extension Manager window shown back in Fig. 82.
Click on the “English Spelling dictionaries” extension, and then press the “Options” button which appears as in Figure 11.
Unfortunately, there appears to be no API for accessing these Hunspell options.
The best that can be done is to use a dispatch message to open the “English Sentence Checking” dialog in Fig. 81.
This done by calling Write.open_sent_check_options():
GUI.set_visible(True,doc)# Office must be visible...Lo.delay(2000)Write.open_sent_check_options()# for the dialog to appear
Write.open_sent_check_options() uses an .uno:OptionsTreeDialog dispatch along with an URL argument for the dialog’s XML definition file:
The XML file’s location is obtained in two steps.
First the ID of the Hunspell service (org.openoffice.en.hunspell.dictionaries) is passed to XPackageInformationProvider.getPackageLocation()
to obtain the spell checker’s installation folder.
Fig. 83 shows a hunspell install directory.
The directory contains a dialog sub-directory, which holds an XXX.xdl file that defines the dialog’s XML structure and data.
The XXX name will be Office’s locale language, which in this case is “en”.
The URL required by the OptionsTreeDialog dispatch is constructed by appending /dialog/en.xdl to the installation folder string.
Write.print_meaning() calls XThesaurus.queryMeanings(), and prints the array of results:
# in the Write class@staticmethoddefprint_meaning(word:str,thesaurus:XThesaurus,loc:Locale|None=None)->int:iflocisNone:loc=Locale("en","US","")meanings=thesaurus.queryMeanings(word,loc,tuple())ifmeaningsisNone:print(f"'{word}' NOT found int thesaurus")print()return0m_len=len(meanings)print(f"'{word}' found in thesaurus; number of meanings: {m_len}")fori,meaninginenumerate(meanings):print(f"{i+1}. Meaning: {meaning.getMeaning()}")synonyms=meaning.querySynonyms()print(f" No. of synonyms: {len(synonyms)}")forsynonyminsynonyms:print(f" {synonym}")print()returnm_len
In a similar way to XSpellChecker.spell(), XThesaurus.queryMeanings() requires a locale and an optional tuple of properties.
print_meaning() utilizes a default of American English, and no properties.
If you need a non-English thesaurus which isn’t part of Office, then look through the dictionary extensions at https://extensions.libreoffice.org/?Tags%5B%5D=50;
many include a thesaurus with the dictionary.
Office’s default grammar checker (or proof reader) is Lightproof, a Python application developed by László Németh.
Lightproof.py, and its support files, are installed in the same folder as the spell checker and thesaurus; on my machine that’s \share\extensions\dict-en.
Older versions of Lightproof are available from OpenOffice’s extensions website at https://extensions.services.openoffice.org/project/lightproof.
One reason for downloading the old version is that it contains documentation on adding new grammar rules missing from the version installed in Office.
There are a number of alternative grammar checkers for Office, such as LanguageTool which are easily added to Office as extensions via the “Language Tools”
When these examples were first coded, by default the default Lightproof for grammar checking, but it doesn’t have a very extensive set of built-in
grammar rules (it seems best at catching punctuation mistakes).
A switch to LanguageTool was made because of its larger set of rules, and its support for many languages.
It also can be used as a standalone Java library, separate from Office, and that its site includes lots of documentation.
Perhaps its biggest drawback is that it requires Java 8 or later.
Another issue is that LanguageTool and Lightproof cannot happily coexist inside Office.
Lightproof must be disabled and LanguageTool enabled via the Options, Language Settings, Writing aids, “Available language modules” pane at the top of Fig. 85.
org.languagetool.openoffice.Main refers to the LanguageTool extension, while org.libreoffice.comp.pyuno.Lightproof.en is the English version of Lightproof.
This information can be used to set the proof reader. LanguageTool is made the default by calling Write.set_configured_services() like so:
# in the Write class@staticmethoddefset_configured_services(lingo_mgr:XLinguServiceManager2,service:str,impl_name:str,loc:Locale|None=None)->bool:cargs=CancelEventArgs(Write.set_configured_services.__qualname__)cargs.event_data={"lingo_mgr":lingo_mgr,"service":service,"impl_name":impl_name,}_Events().trigger(WriteNamedEvent.CONFIGURED_SERVICES_SETTING,cargs)ifcargs.cancel:returnFalseservice=cargs.event_data["service"]impl_name=cargs.event_data["impl_name"]iflocisNone:loc=Locale("en","US","")impl_names=(impl_name,)lingo_mgr.setConfiguredServices(f"com.sun.star.linguistic2.{service}",loc,impl_names)_Events().trigger(WriteNamedEvent.CONFIGURED_SERVICES_SET,EventArgs.from_args(cargs))returnTrue
The method utilizes XLinguServiceManager.setConfiguredServices() to attach a particular implementation service
(eg: LanguageTool) to a specified linguistic service (eg: the Proofreader).
The kinds of errors reported by the proof reader can be adjusted through Office’s GUI.
One configuration pane, used by both Lightproof and LanguageTool, is in the “English Sentence Checking” dialog shown back in Fig. 81.
If you look closely, the first group of check boxes are titled “Grammar checking”.
If you install LanguageTool, Office’s Tools menu will be modified to contain a new “LanguageTool” sub-menu shown in Fig. 86.
The “Options” menu item in the LanguageTool sub-menu brings up an extensive set of options, reflecting the greater number of grammar rules in the checker (see Fig. 87).
In Lingo the proof reader is loaded and called like so:
# load & use proof reader (Lightproof or LanguageTool)proofreader=Write.load_proofreader()print("Proofing...")num_errs=Write.proof_sentence("i dont have one one dogs.",proofreader)print(f"No. of proofing errors: {num_errs}")
The output is:
Proofing...
G* This sentence does not start with an uppercase letter. in: 'i'
Suggested change: 'I'
G* Spelling mistake in: 'dont'
Suggested change: 'don't'
G* Word repetition in: 'one one'
Suggested change: 'one'
No. of proofing errors: 3
The proof reader isn’t accessed through the linguistics manager; instead a Proofreader service is created, and its interfaces employed.
A simplified view of the services and interfaces are shown in Fig. 88.
# in the Write class@staticmethoddefload_proofreader()->XProofreader:proof=mLo.Lo.create_instance_mcf(XProofreader,"com.sun.star.linguistic2.Proofreader",raise_err=True)returnproof
XProofreader.doProofreading() requires a locale and properties in the same way as the earlier spell checking and thesaurus methods.
It also needs two indices for the start and end of the sentence being checked, and a document ID which is used in the error results.
The results are returned as an array of SingleProofreadingError objects, one for each detected error.
It’s worth having a look at the documentation for the SingleProofreadingError class (use lodocSingleProofreadingError),
since the object contains more information than is used in Write.print_proof_error();
for example, the ID of the grammar rule that was ‘broken’, a full comment string, and multiple suggestions in a String array.
Grammar rule IDs are one area where the proof reader API could be improved.
The XProofreader interface includes methods for switching on and off rules based on their IDs,
but there’s no way to find out what these IDs are except by looking at SingleProofreadingError objects.
An oft overlooked linguistics API feature is the ability to guess the language used in a string,
which is implemented by one service, LanguageGuessing, and a single interface, XLanguageGuessing.
The documentation for XLanguageGuessing includes a long list of supported languages, including Irish Gaelic, Scots Gaelic, and Manx Gaelic.
There are two examples of language guessing in Lingo:
# from lingo example# guess the languageloc=Write.guess_locale("The rain in Spain stays mainly on the plain.")Write.print_locale(loc)iflocisnotNone:print("Guessed language: "+loc.Language)loc=Write.guess_locale("A vaincre sans p�ril, on triomphe sans gloire.")iflocisnotNone:print("Guessed language: "+loc.Language)
Write.guess_locale() creates the service, its interface, and calls XLanguageGuessing.guessPrimaryLanguage():
# in the Writer class@staticmethoddefguess_locale(test_str:str)->Locale|None:guesser=Lo.create_instance_mcf(XLanguageGuessing,"com.sun.star.linguistic2.LanguageGuessing")ifguesserisNone:Lo.print("No language guesser found")returnNonereturnguesser.guessPrimaryLanguage(test_str,0,len(test_str))
XLanguageGuessing actually guesses a Locale rather than a language, and it includes information about the language, country and a variant BCP 47 language label.
So there was a switch to a combined Office/python approach – the outer loop in Lingo File still utilizes XParagraphCursor to scan the paragraphs,
but the sentences in a paragraph are extracted using Write.split_paragraph_into_sentences() that splits sentences into a list of strings.
defcheck_sentences(doc:XTextDocument)->None:# load spell checker, proof readerspeller=Write.load_spell_checker()proofreader=Write.load_proofreader()para_cursor=Write.get_paragraph_cursor(doc)para_cursor.gotoStart(False)# go to start test; no selectionwhile1:para_cursor.gotoEndOfParagraph(True)# select all of paragraphcurr_para_str=para_cursor.getString()iflen(curr_para_str)>0:print(f"\n>> {curr_para_str}")sentences=Write.split_paragraph_into_sentences(curr_para_str)forsentenceinsentences:# print(f'S <{sentence}>')Write.proof_sentence(sentence,proofreader)Write.spell_sentence(sentence,speller)ifpara_cursor.gotoNextParagraph(False)isFalse:break
Write.load_spell_checker() does not use LinguServiceManager manager to create SpellChecker.
For a yet unknown reason when speller comes from lingo_mgr.getSpellChecker() it errors when passed to methods such as Write.spell_word().
For this reason com.sun.star.linguistic2.SpellChecker is used to get a instance of XSpellChecker,
# in the Write class@staticmethoddefload_spell_checker()->XSpellChecker:# lingo_mgr = Lo.create_instance_mcf(# XLinguServiceManager, "com.sun.star.linguistic2.LinguServiceManager", raise_err=True# )# return lingo_mgr.getSpellChecker()speller=Lo.create_instance_mcf(XSpellChecker,"com.sun.star.linguistic2.SpellChecker",raise_err=True)returnspeller@classmethoddefspell_sentence(cls,sent:str,speller:XSpellChecker,loc:Locale|None=None)->int:words=re.split("\W+",sent)count=0forwordinwords:is_correct=cls.spell_word(word=word,speller=speller,loc=loc)count=count+(0ifis_correctelse1)returncount
The poorly written badGrammar.odt is shown in Fig. 89.
The output from Lingo File when given badGrammar.odt:
>> I have a dogs. I have one dogs.
G* Possible agreement error in: "a dogs"
Suggested change: "a dog"
>> I allow of of go home. i dogs. John don’t like dogs. So recieve
no cats also.
G* Word repetition in: "of of"
Suggested change: "of"
G* This sentence does not start with an uppercase letter in: "i"
Suggested change: "I"
G* Grammatical problem in: "dogs"
Suggested change: "dog"
G* 'Also' at the end of sentence in: "also"
Suggested change: "as well"
* "recieve" is unknown. Try:
No. of names: 8
"receive" "relieve" "retrieve" "reprieve"
"reverie" "recitative" "Recife" "reserve"
The grammar errors (those starting with "G*") are produced by the LanguageTool
proof checker. If the default Lightproof checker is utilized instead, then less errors are
found:
>> I have a dogs. I have one dogs.
>> I allow of of go home. i dogs. John don’t like dogs. So recieve
no cats also.
G* Word duplication? in: "of of"
Suggested change: "of"
G* Missing capitalization? in: "i"
Suggested change: "I"
* "recieve" is unknown. Try:
No. of names: 8
"receive" "relieve" "retrieve" "reprieve"
"reverie" "recitative" "Recife" "reserve"
On larger documents, it’s a good idea to redirect the voluminous output to a temporary file so it can be examined easily.
The output can be considerably reduced if LanguageTool’s unpaired rule is disabled, via the Options dialog in Fig. 87.
Fig. 90 shows the dialog with the “Unpaired” checkbox deselected in the Punctuation section.
Fig. 90 :The LanguageTool Options Dialog with the Unpaired Rule Deselected.
The majority of the remaining errors are words unknown to the spell checker, such as names and places, and British English spellings.
Most of the grammar errors relate to how direct speech is written.
The grammar checker mistakenly reports an error if the direct speech ends with a question mark or exclamation mark without a comma after the quoted text.