Spell Checking and Hyphenation
A batch of generated letters can be proofread before it's sent, and a PDF with narrow columns looks better when long words are hyphenated at the end of a line. ServerTextControl checks spelling and hyphenates words with the help of TX Spell .NET. Your code turns both on, reads and corrects the misspelled words of every part of a document, sets the language that decides which dictionary is used and adjusts where words are divided.
Spell checking while users type in the browser, with dialog boxes and user dictionaries, is described in Spell Checking in the Document Editor section.
What You Need
Spell checking and hyphenation are calculated by TX Spell .NET, a separate Text Control product. For .NET applications, it's available as the NuGet package TXTextControl.TXSpell.Core.SDK, which copies its Dictionaries, HyphenationLists, LanguageRecognition and SynonymLists folders into the output of the project. TX Spell .NET supports the Hunspell dictionaries of OpenOffice.org, which cover more than 60 languages, each under its own license terms. For licensing questions, contact the Text Control sales team.
A spell checking component is connected with ServerTextControl.SpellChecker, which must be set to a TX Spell .NET object; the TX Spell .NET documentation describes how to create it. When no component is connected, the property is null. With a connected component, three properties of ServerTextControl take effect:
| Property | When true |
|---|---|
| IsSpellCheckingEnabled | The text is checked, and the misspelled words of the document are collected in MisspelledWords |
| IsHyphenationEnabled | Words that don't fit at the end of a line are divided |
| IsLanguageDetectionEnabled | A language is detected for all text that has the neutral language |
Hyphenation divides words at the end of a line, so it changes where the lines and the pages of a document break. Set IsHyphenationEnabled before you save the document in a paginated format such as PDF.
Read and Correct Misspelled Words
Each text part of a document has a MisspelledWordCollection: ServerTextControl.MisspelledWords for the main text and IFormattedText.MisspelledWords for each part in TextParts. The following class prints the misspelled words of all text parts and replaces those for which a correction is known. Call it with a ServerTextControl whose SpellChecker is connected and which contains the document to check:
using TXTextControl;
public static class Proofreader
{
public static void CorrectSpelling(ServerTextControl tx, IDictionary<string, string> corrections)
{
tx.IsSpellCheckingEnabled = true;
// The main text, text frames, headers and footers
foreach (IFormattedText textPart in tx.TextParts)
{
MisspelledWordCollection words = textPart.MisspelledWords;
Console.WriteLine($"{textPart.GetType().Name}: {words.GetCount(MisspelledWordKind.Normal)} misspelled, " +
$"{words.GetCount(MisspelledWordKind.Duplicate)} repeated");
// From the last word to the first, because Remove changes the collection
for (int number = words.Count; number >= 1; number--)
{
MisspelledWord word = words[number];
string language = word.Culture?.Name ?? "neutral";
Console.WriteLine($" {word.Text} at {word.Start} ({language}), repeated: {word.IsDuplicate}");
if (corrections.TryGetValue(word.Text, out string? corrected))
{
// Replaces the word in the document with the corrected text
words.Remove(word, corrected);
}
}
}
}
}
The code works as follows:
- GetCount counts the words of a MisspelledWordKind:
Normalfor misspelled words,Duplicatefor a correctly spelled word that repeats the word in front of it,Ignoredfor ignored words orAll. - The indexer Item takes a number from 1 to
Count, in the order of the text. - A MisspelledWord has its Text, the one-based Start position, its Length and its Culture, which is
nullwhen the word has no specific language. IsDuplicate marks a repeated word. - Remove with a corrected text replaces the word in the document. Without a text, it removes only the entry from the collection and leaves the word as it is.
To accept a word without changing it, set IsIgnored to true: the word stays in the collection with the kind Ignored. Ignore replaces the text of a word and marks it as ignored in one step. GetItem with a zero-based text position returns the misspelled word at that position, or the next one after it.
To exclude the text of a field from spell checking, for example a field with a customer name, set TextField.IsSpellCheckingEnabled to false.
Set the Language of Text
Spell checking and hyphenation use the dictionary of the language of the text. The language is a character attribute, so one document can contain text in several languages:
- For a piece of text, set Selection.Culture to a
CultureInfo, as the example of Insert Formatted Text does for a German paragraph. The default isnull, the neutral language. - For all text of a style, set FormattingStyle.Culture of a paragraph or inline style.
- For text without a language, turn on
IsLanguageDetectionEnabled. The language is then detected for all text parts with the neutral language.
Hyphenate Words
With IsHyphenationEnabled set to true, the HyphenateWord event occurs for each word that doesn't fit at the end of a line. Its HyphenateWordEventArgs contain the position at which the connected spell checker divides the word, and your handler can change it. The following class turns hyphenation on and logs each word that is hyphenated:
using TXTextControl;
public static class Hyphenation
{
public static void Enable(ServerTextControl tx)
{
tx.HyphenateWord += (sender, e) =>
{
string language = e.Culture?.Name ?? "neutral";
Console.WriteLine($"{e.Word} ({language}): divided after {e.DividePos} of at most {e.MaxDividePos} characters");
};
tx.IsHyphenationEnabled = true;
}
}
The code works as follows:
- Word is the word to hyphenate and Culture its language.
- MaxDividePos is the number of characters that fit on the line: with 3, at most the first 3 characters stay on it.
- DividePos is the position calculated by the connected spell checker, or 0 without one. The word is divided at this position if it's less than or equal to
MaxDividePos. To divide a word elsewhere, for example according to rules of your own, the handler setsDividePosto another position.
To allow a word to be divided at one position only, insert a non-visible hyphen there with ControlChars.NonVisibleHyphen, as Insert Special Characters describes. The hyphen appears only when the word is broken at that position.
Check Spelling Without TX Spell .NET
When IsSpellCheckingEnabled is true and no component is connected with SpellChecker, ServerTextControl raises SpellCheckText whenever text has changed and must be checked. Your handler checks the text with a spell checker of its own:
- SpellCheckTextEventArgs.Text is the text to check, and Culture its language.
- The handler sets MisspelledWords to an array of
MisspelledWordobjects, one for each misspelled word the text contains. The MisspelledWord constructor takes the one-based start position and the length of the word.
Events lists SpellCheckText with the other events of ServerTextControl.
Next Steps
- Text: set the language and other attributes of text.
- Spell Checking in the Document Editor: check spelling while users type.
- Events: the proofing events and all other events of
ServerTextControl.