Loading and Managing Dictionaries
Every check of TX Spell .NET runs against the dictionaries in one collection. Which dictionaries it holds decides what is correct: English only by default, English and German once you add the German dictionary, or a specialist vocabulary on top. Here is where the spell checker finds dictionary files, which one it loads by itself, and how your code adds, switches off and removes dictionaries while the application runs.
Where the Spell Checker Finds Dictionaries
TX Spell .NET looks for dictionary files in its default dictionary folder, a folder named Dictionaries next to the application or, on the development machine, below the Assembly folder of the installation. Both places are what the default of DictionariesDirectoryPath, "(Auto)", stands for; set the property to keep the dictionaries elsewhere. Where the Spell Checker Looks describes the lookup, and Dictionaries Not Found lists the messages when a folder is missing.
Which Dictionary Is Loaded First
The Language property of the spell checker chooses the dictionary it loads by itself, the default dictionary. Its value is "(Auto)" when you declare a TXSpellChecker in XAML:
- The spell checker loads the dictionary of the language the application runs in, if the default folder has it.
- Otherwise it loads a dictionary of a close language: in a British English environment with only en_US.dic and de_DE_frami.dic in the folder, it takes en_US.dic.
- Otherwise it loads en_US.dic, and if that is missing too, the first dictionary in the folder.
To fix the default dictionary instead, set Language to the file name of a dictionary in the default folder. txSpellChecker1 is the resource of the window, which the code-behind gets with FindResource, as As-You-Type Checking shows:
// Use the German dictionary as the default dictionary
txSpellChecker1.Language = "de_DE_frami.dic";
A value ending in .txd loads a user dictionary instead, and "(none)" loads no dictionary at all, for an application that adds only dictionaries of its own. The chosen dictionary has its IsSelectedAsDefault property set to true.
See Which Dictionaries Are There
Two properties answer the two questions a program asks:
- AvailableDictionaries is an array of the file names in the default folder, whether they are loaded or not, such as
de_DE_frami.dicanden_US.dic. It is the list to offer in a language menu of your application. - Dictionaries is the DictionaryCollection of the dictionaries that are loaded and used.
Each entry of Dictionaries is a Dictionary: an OpenOfficeDictionary for a Hunspell dictionary, or a UserDictionary for a word list of your own. These properties describe it:
| Property | Holds |
|---|---|
| Name | The file name, such as en_US.dic |
| DisplayName | The name the dialogs show; by default the file name |
| Language | The language, taken from the file name, such as German (Germany) for de_DE_frami.dic; null when the name carries none |
| IsSpellCheckingEnabled | Whether words are checked against it; true by default |
| IsGetSuggestionsEnabled | Whether it provides suggestions; true by default |
| DictionaryEncoding | The encoding of the dictionary, a System.Text.Encoding |
Add a Dictionary
Copy the files of the dictionary into the default folder, as Hunspell and OpenOffice Dictionaries describes. Then create an OpenOfficeDictionary with the file name and add it with Add, for example in the constructor of the window:
using System.Windows;
using TXTextControl.Proofing;
using TXTextControl.WPF.Proofing;
public partial class MainWindow : Window
{
private readonly TXSpellChecker txSpellChecker1;
public MainWindow()
{
InitializeComponent();
// The spell checker declared in Window.Resources
txSpellChecker1 = (TXSpellChecker)FindResource("txSpellChecker1");
// Check German text as well as English text
OpenOfficeDictionary german = new OpenOfficeDictionary("de_DE_frami.dic");
txSpellChecker1.Dictionaries.Add(german);
}
}
The code works as follows:
FindResourcereturns the spell checker declared in MainWindow.xaml; theOpenOfficeDictionaryclass comes from theTXTextControl.Proofingnamespace, the spell checker fromTXTextControl.WPF.Proofing.- The constructor takes the name of the .dic or .aff file. A name without a path refers to the default folder. The file is read only when the dictionary is added to the collection.
Addloads the dictionary, checks that it is valid, and returns its index in the collection.- The new dictionary gets its language from its file name, here German (Germany).
From now on, a word is correct if one of the enabled dictionaries knows it. In a test with the sentence This sentense has a mistake. Dieser Satz hat einen Fehlr., English alone reports sentense, Dieser, Satz, einen and Fehlr; with the German dictionary added, only sentense and Fehlr remain.
To check a text in one language only, pass the language to Check: Check(text, new CultureInfo("de-DE")) uses the German dictionaries and reports the English words of the same sentence. Multilingual Documents and Language Scopes covers texts in several languages.
Check While a Large Dictionary Loads
By default, Add loads a dictionary completely before the spell checker uses it. LoadDictionaryDelayed of the DictionaryCollection changes this: set to true, it loads dictionaries partially when they are added, and the spell checker checks text while the rest is still loading:
// Check text while the German dictionary is still loading
txSpellChecker1.Dictionaries.LoadDictionaryDelayed = true;
txSpellChecker1.Dictionaries.Add(new OpenOfficeDictionary("de_DE_frami.dic"));
The dictionary is loaded when it is added, so set the property before Add. The price is speed: until the dictionary is loaded completely, checking is slower than with a fully loaded one. For the full checking speed, leave the property at its default, false.
Load a Dictionary From Memory
A dictionary doesn't have to be a file in a folder. A second constructor takes the lines of the .dic and the .aff file as string arrays, together with the language, so the dictionary can come from a database or from resources embedded in your assembly:
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
using TXTextControl.Proofing;
private static string[] ReadLines(string resourceName, Encoding encoding)
{
List<string> lines = new List<string>();
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream, encoding))
{
string line;
while ((line = reader.ReadLine()) != null)
{
lines.Add(line);
}
}
return lines.ToArray();
}
private void AddEmbeddedDictionary()
{
// The German files are encoded in ISO-8859-1, as the SET line of the .aff file says
Encoding encoding = Encoding.GetEncoding("ISO-8859-1");
// The resource names depend on the default namespace and the folder of the files
OpenOfficeDictionary german = new OpenOfficeDictionary(
ReadLines("MyApp.Dictionaries.de_DE_frami.dic", encoding),
ReadLines("MyApp.Dictionaries.de_DE_frami.aff", encoding),
new CultureInfo("de-DE"));
txSpellChecker1.Dictionaries.Add(german);
}
Add the two files to the project with the build action Embedded Resource. Read them with the encoding that the SET line of the .aff file names: SET ISO8859-1 for the German dictionary, SET UTF-8 for the English one. The blog article TX Spell .NET 3.0: Loading Dictionaries from Embedded Resources describes the approach.
Switch Off or Remove a Dictionary
A dictionary can stay loaded but play a smaller part:
- Set
IsSpellCheckingEnabledtofalse, and the dictionary no longer decides whether a word is correct, but can still provide suggestions. - Set
IsGetSuggestionsEnabledtofalse, and it checks words but provides no suggestions.
To take a dictionary out entirely, find it with GetItem and pass it to Remove:
Dictionary german = txSpellChecker1.Dictionaries.GetItem("de_DE_frami.dic");
if (german != null)
{
txSpellChecker1.Dictionaries.Remove(german);
}
GetItem takes the full name, with the extension, and returns null when there is no such dictionary. Add and Remove throw an exception while the spell check dialog is open. Only a user dictionary can be added or removed then, and only while the options dialog that the Options... button of the spell check dialog opened is shown.
React When Dictionaries Change
The spell checker raises DictionaryAdded and DictionaryRemoved whenever the collection changes, whether your code or the user made the change. The Dictionary property of the arguments is the dictionary concerned, for example to update a language menu of your application. Events lists all events.
What Users Can Do
Users switch a dictionary off for checking or for suggestions on the Spell Checking Dictionaries tab of the options dialog, and choose the dictionary the suggestions come from in the Suggestions Dictionary list of the spell check dialog. Options Dialog and Suggestion Controls describe both, and how to hide a dictionary or give it a display name. With the ribbon of TX Text Control, the Settings group of the Proofing tab also has a Load Dictionary button.
Next Steps
- User Dictionaries: let users add words, and keep them.
- Multilingual Documents and Language Scopes: check each language of a document with its dictionary.
- Language Detection: find out which languages a text contains, and load their dictionaries.