# Language Detection

> Find the languages of mixed text in WPF: DetectLanguageScopes on TXSpell or TXSpellChecker, IsLanguageDetectionEnabled in TextControl, detectable languages.

- **Product:** TX Spell .NET for WPF
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Spell .NET for WPF > Dictionaries and Languages > Language Detection
- **2371 words**
- **Web URL:** https://docs.textcontrol.com/tx-spell-dotnet-wpf/dictionaries/language-detection/
- **LLMs URL:** https://docs.textcontrol.com/tx-spell-dotnet-wpf/dictionaries/language-detection/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-spell-dotnet-wpf/dictionaries/language-detection/llms-full.txt

---

Which language is this sentence written in? TX Spell .NET answers that question for text that doesn't say: a document converted from plain text, pasted from a web page, or saved by an application that stores no language. Language detection splits such a text into *language scopes*, sections that each have one language, so that every part is checked, hyphenated and given suggestions in the right language. It works in TX Text Control without code and on any string in code.

### How Language Detection Works

The spell checker recognizes more than 30 languages and marks where one language ends and the next begins. A few properties of the method matter in practice:

- **A sentence is enough.** One sentence of four or more words is usually enough to detect its language. Shorter pieces may stay without a language.
- **No dictionaries are needed.** Detection uses its own data, the file *languageRecognition.resources*, not the dictionaries of the detected languages.
- **Scopes can be nested.** A German phrase in brackets inside an English sentence becomes a scope of its own, and bidirectional text that mixes, for example, Arabic and English is split as well.
- **Only the languages you allow are detected.** The spell checker looks for the languages in its list of detectable languages; others are counted as one of those or left without a language.

Documents from TX Text Control and from Microsoft Word usually carry the language of their text already. Detection is for the rest.

### Detect Languages in TX Text Control

A `TextControl` with a connected spell checker can detect languages by itself. Set its [IsLanguageDetectionEnabled](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/islanguagedetectionenabled-property/llms-full.txt) property to `true`, in the **Properties** window or in code:

```csharp
// Detect a language for all text without one
textControl1.IsLanguageDetectionEnabled = true;
```

Every piece of text with a neutral language then gets the language that was detected for it. The detection needs a spell checker connected through the [SpellChecker](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/spellchecker-property/llms-full.txt) property, as in [Create Your First WPF Application](https://docs.textcontrol.com/tx-spell-dotnet-wpf/getting-started/tx-text-control/first-application/llms-full.txt).

The status bar of TX Text Control shows the language of the text at the input position, so the user sees which language a word was given. Its [ShowLanguage](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/statusbar/showlanguage-property/llms-full.txt) property turns this field on and off. The **Language** group of the **Proofing** tab holds the commands to set and detect languages.

### Detect Language Scopes in Code

[DetectLanguageScopes](https://docs.textcontrol.com/tx-spell-dotnet-wpf/reference/txtextcontrol-wpf-proofing/txspellchecker/detectlanguagescopes-method/llms-full.txt) detects the language scopes of a string and fills [LanguageScopes](https://docs.textcontrol.com/tx-spell-dotnet-wpf/reference/txtextcontrol-wpf-proofing/txspellchecker/languagescopes-property/llms-full.txt) with them. The `TXSpellChecker` of a window and the [TXSpell](https://docs.textcontrol.com/tx-spell-dotnet-wpf/reference/txtextcontrol-proofing/txspell/llms-full.txt) class for code without a user interface have the same members. This console application uses `TXSpell` from the package `TXTextControl.TXSpell.Core.SDK`, as in [Checking Text in Code](https://docs.textcontrol.com/tx-spell-dotnet-wpf/getting-started/in-code/llms-full.txt):

```csharp
using System;
using TXTextControl.Proofing;

TXSpell spell = new TXSpell();

// Initialize the new instance before using it
spell.Create();

string text = "This is a test. Dieses ist ein Test. Esto es una prueba.";

spell.DetectLanguageScopes(text);

foreach (LanguageScope scope in spell.LanguageScopes)
{
    Console.WriteLine($"{scope.Language?.Name} Start {scope.Start} Length {scope.Length}: \"{text.Substring(scope.Start, scope.Length)}\"");
}
```

The console shows three scopes:

```text
en Start 0 Length 16: "This is a test. "
de Start 16 Length 21: "Dieses ist ein Test. "
es Start 37 Length 19: "Esto es una prueba."
```

The code works as follows:

- Each [LanguageScope](https://docs.textcontrol.com/tx-spell-dotnet-wpf/reference/txtextcontrol-proofing/languagescope/llms-full.txt) has a [Language](https://docs.textcontrol.com/tx-spell-dotnet-wpf/reference/txtextcontrol-proofing/languagescope/language-property/llms-full.txt), a neutral `CultureInfo` such as `en` or `de`, and a [Start](https://docs.textcontrol.com/tx-spell-dotnet-wpf/reference/txtextcontrol-proofing/languagescope/start-property/llms-full.txt) and [Length](https://docs.textcontrol.com/tx-spell-dotnet-wpf/reference/txtextcontrol-proofing/languagescope/length-property/llms-full.txt) in the text, counting from 0.
- `Language` is `null` for a scope whose language couldn't be detected, for example a text that is too short, so the code reads it with `?.`.
- The space after a sentence belongs to the scope of that sentence.

With the `TXSpellChecker` resource of a window, which the code-behind gets with `FindResource`, write `txSpellChecker1.DetectLanguageScopes(text)` and read `txSpellChecker1.LanguageScopes` instead.

The *LanguageScopes* property holds a [LanguageScopeCollection](https://docs.textcontrol.com/tx-spell-dotnet-wpf/reference/txtextcontrol-proofing/languagescopecollection/llms-full.txt). Its [GetItem](https://docs.textcontrol.com/tx-spell-dotnet-wpf/reference/txtextcontrol-proofing/languagescopecollection/getitem-method/llms-full.txt) method returns the scope at a text position, or, with a language as the second argument, the scope of that language at or after the position, and the first scope of that language when none follows.

The sample that came with language detection colors each scope of a text in a different color, here English, French, German and Spanish:

![A text with English sentences in red, a French sentence in green, a German sentence in blue and a Spanish sentence in orange, each colored by its detected language scope.](https://docs.textcontrol.com/assets/img/tx-spell-dotnet-wpf/language-scopes-sample.aa1da5c6.webp)

### Choose the Detectable Languages

[DetectableLanguageScopes](https://docs.textcontrol.com/tx-spell-dotnet-wpf/reference/txtextcontrol-wpf-proofing/txspellchecker/detectablelanguagescopes-property/llms-full.txt) is the list of languages the spell checker looks for. By default, it holds seven of the most widely spoken languages: Arabic (`ar`), German (`de`), English (`en`), Spanish (`es`), French (`fr`), Portuguese (`pt`) and Russian (`ru`).

A language that isn't in the list isn't detected. Italian text, for example, is detected as Spanish or not at all with the default list. Set the list to the languages your documents contain:

```csharp
using System.Globalization;

txSpellChecker1.DetectableLanguageScopes = new CultureInfo[]
{
    new CultureInfo("en"),
    new CultureInfo("de"),
    new CultureInfo("it"),
    new CultureInfo("nl")
};
```

The list takes neutral cultures only: `new CultureInfo("de")` works, while a specific culture such as `new CultureInfo("de-DE")` throws an `ArgumentException`. These languages can be detected:

|  |  |  |  |  |
|---|---|---|---|---|
| Afrikaans (`af`) | Arabic (`ar`) | Armenian (`hy`) | Belarusian (`be`) | Bulgarian (`bg`) |
| Catalan (`ca`) | Croatian (`hr`) | Czech (`cs`) | Danish (`da`) | Dutch (`nl`) |
| English (`en`) | Estonian (`et`) | French (`fr`) | Galician (`gl`) | German (`de`) |
| Greek (`el`) | Hebrew (`he`) | Italian (`it`) | Lithuanian (`lt`) | Norwegian (`no`) |
| Occitan (`oc-FR`) | Persian (`fa`) | Polish (`pl`) | Portuguese (`pt`) | Romanian (`ro`) |
| Russian (`ru`) | Serbian (`sr`) | Slovak (`sk`) | Slovenian (`sl`) | Spanish (`es`) |
| Swedish (`sv`) | Ukrainian (`uk`) | Urdu (`ur`) | Vietnamese (`vi`) |  |

Occitan is the one language written with its region, `oc-FR`.

### Use the Detected Languages

Detection tells you which languages a text contains, so it is a way to decide which dictionaries to load: add the dictionary of each detected language, and the text is checked in all of them. [Loading and Managing Dictionaries](https://docs.textcontrol.com/tx-spell-dotnet-wpf/dictionaries/managing/llms-full.txt) shows how to add a dictionary, and [Multilingual Documents and Language Scopes](https://docs.textcontrol.com/tx-spell-dotnet-wpf/dictionaries/multilingual/llms-full.txt) how the spell checker picks the dictionary for each piece of text.

### Where the Language Recognition Data Is

Detection reads *languageRecognition.resources* from the folder in [LanguageRecognitionDirectoryPath](https://docs.textcontrol.com/tx-spell-dotnet-wpf/reference/txtextcontrol-wpf-proofing/txspellchecker/languagerecognitiondirectorypath-property/llms-full.txt). Its default, "(Auto)", is the folder *LanguageRecognition* next to the application, or, on the development machine, below the *Assembly* folder of the TX Spell .NET installation.

- **In .NET projects,** the TX Spell .NET packages copy the folder *LanguageRecognition* into the output folder when you build.
- **In .NET Framework projects,** ship the folder with the application; see [Deploying .NET Framework Applications](https://docs.textcontrol.com/tx-spell-dotnet-wpf/deployment/dotnet-framework/llms-full.txt).
- **To keep the file elsewhere,** set `LanguageRecognitionDirectoryPath` to its folder. The folder must exist; otherwise the property throws an `ArgumentException`.

Without the file, `DetectLanguageScopes` fails with an exception. [Dictionaries Not Found](https://docs.textcontrol.com/tx-spell-dotnet-wpf/troubleshooting/dictionaries/llms-full.txt) lists the messages when a language data folder is missing.

### Next Steps

- [Multilingual Documents and Language Scopes](https://docs.textcontrol.com/tx-spell-dotnet-wpf/dictionaries/multilingual/llms-full.txt): check texts that mix languages.
- [Loading and Managing Dictionaries](https://docs.textcontrol.com/tx-spell-dotnet-wpf/dictionaries/managing/llms-full.txt): add the dictionaries of the detected languages.
- [Checking Text in Code](https://docs.textcontrol.com/tx-spell-dotnet-wpf/getting-started/in-code/llms-full.txt): the console application this sample builds on.

---

## Nearby

- **Previous:** [Multilingual Documents and Language Scopes](https://docs.textcontrol.com/tx-spell-dotnet-wpf/dictionaries/multilingual/llms-full.txt)
- **Next:** [Right-to-Left Languages](https://docs.textcontrol.com/tx-spell-dotnet-wpf/dictionaries/right-to-left/llms-full.txt)
