# LanguageTool

> Proofread text with LanguageTool, the open-source grammar, spelling and style checker, in more than thirty languages. Check a draft and get every issue with the words it is about and what to write instead, or correct it outright and get the finished text back ready to send. Works on plain text or on HTML, so an email body or a page can be checked without its tags being reported as mistakes, and a long document is checked in as many requests as it takes and reported as one answer. Detect which language something is written in to route it, list the languages LanguageTool knows, and turn individual rules or whole categories off. Works with no account at all; add a LanguageTool Premium username and API key to raise the limits, turn on the Premium rules, and manage the personal dictionaries that stop your product and customer names being reported as misspellings.

App · Dictionaries & Language · 8 actions. Web page: https://docs.lodol.com/docs/integrations/languagetool

## Actions

### Add a dictionary word

Add one word to a personal dictionary so LanguageTool stops reporting it as a misspelling - a product name, a customer, a house spelling. A dictionary that does not exist yet is created by adding to it. Adding a word that is already there is reported as such rather than failing, so the step is safe to re-run. Needs a LanguageTool Premium username and API key on the connection.

**Inputs**

- Word (`word`, text, required): The word to add. A single word, not a phrase: LanguageTool stores no spaces, so add each word on its own. The word counts for every language the account checks, not only the one it came from.
- Dictionary (`dictionary`, text): Which personal dictionary to use. Leave empty for the account's default one. A dictionary that does not exist yet is created the first time a word is added to it.

**Outputs**

- `added` (true/false)
- `already_present` (true/false)
- `dictionary` (text)
- `word` (text)

**Example output**

```json
{
  "added": true,
  "already_present": false,
  "dictionary": null,
  "word": "Lodol"
}
```

### Check service status

Check whether LanguageTool is answering, and how quickly. This is the one action that reports a problem as a value instead of failing the step, so a workflow can decide what to do about it. Being rate limited is reported separately from being down, and the answer says whether the connection carries Premium credentials.

**Inputs**: None.

**Outputs**

- `has_credentials` (true/false)
- `language_count` (number)
- `message` (text)
- `online` (true/false)
- `rate_limited` (true/false)
- `reachable` (true/false)
- `response_time_ms` (number)
- `status_code` (number)

**Example output**

```json
{
  "has_credentials": false,
  "language_count": 35,
  "message": "LanguageTool is up and checking 35 languages without credentials.",
  "online": true,
  "rate_limited": false,
  "reachable": true,
  "response_time_ms": 148.2,
  "status_code": 200
}
```

### Check text

Proofread a text with LanguageTool and get back every spelling, grammar, punctuation and style issue it finds: what is wrong, the exact words it is about, where they are, and what to write instead. Works on plain text or HTML, in more than thirty languages, and detects the language when you do not name it. Turn individual rules or whole categories off, or go picky for formal writing. No API key required; a Premium connection adds the Premium rules.

**Inputs**

- Text (`text`, text, required): The text to check. Plain text by default; set Input format to HTML to check an email or a page body, and the tags are stepped over rather than reported as mistakes. A long text is checked in as many requests as it takes, 20,000 characters at a time (60,000 with a Premium connection), and comes back as one answer.
- Language (`language`, text): The language the text is written in, as a code such as en-US or de-DE. Leave it on Detect automatically for text arriving from somewhere else. LanguageTool only checks spelling when the variant is named, so 'en' and 'de' are not offered and are refused if typed: pick en-US or en-GB rather than English. Default: `auto`.
- Input format (`input_format`, text): Whether the text is plain prose or HTML. HTML is handed to LanguageTool as an annotated document, so tags, comments and entities are stepped over: 'caf&eacute;' is read as one word, and a heading does not run into the paragraph under it. One of: `text` (Plain text), `html`. Default: `text`.
- Level (`level`, text): How strict to be. Picky turns on the extra rules LanguageTool describes as useful for formal text - typography, style and register - and finds more in a contract than in a chat message. One of: `default`, `picky`. Default: `default`.
- Writer's native language (`mother_tongue`, text): The writer's native language, which turns on LanguageTool's false-friend rules for some language pairs: a German speaker writing English gets told about 'become' for 'bekommen'. It is a fact about the writer, not about the text, so leave it empty unless you know it.
- Preferred variants (`preferred_variants`, text): Which variant to prefer when the language is detected, comma-separated, such as en-GB, de-AT. Detection can tell English from German but not British from American English, and LanguageTool checks no spelling until a variant is chosen, so en-US, de-DE, pt-BR, ca-ES are sent when this is empty. Only used when the language is detected automatically.
- Rules to ignore (`disabled_rules`, text): Rule IDs to turn off, comma-separated, such as UPPERCASE_SENTENCE_START, WHITESPACE_RULE. Every issue reported by this integration carries the ID of the rule that found it, so the way to silence a rule is to run the step once and paste the ID from what came back.
- Categories to ignore (`disabled_categories`, text): Whole categories to turn off, comma-separated, such as TYPOGRAPHY, STYLE, REDUNDANCY. Every issue carries its category ID, so run the step once and paste the ones you do not want.
- Extra rules to run (`enabled_rules`, text): Rule IDs to turn on, comma-separated. These are rules that are off by default; a rule still only runs if the level allows it, so a picky-only rule also needs Level set to picky.
- Extra categories to run (`enabled_categories`, text): Category IDs to turn on, comma-separated. Categories that are off by default, named the same way as the ones to turn off.
- Run only those rules (`enabled_only`, true/false): Run only the rules and categories named above and nothing else. Off by default. This needs at least one rule or category to be named, because otherwise it turns off every check there is. Default: `false`.
- Personal dictionaries (`dictionaries`, text): The personal dictionaries to take words from, comma-separated, so the words in them stop being reported as misspellings. Needs a Premium connection; leave empty for the account's default dictionary.

**Outputs**

- `categories` (list)
- `has_issues` (true/false)
- `input_format` (text)
- `issue_count` (number)
- `issue_types` (list)
- `issues` (list)
- `language` (object)
- `level` (text)
- `preferred_variants` (list)
- `request_count` (number)
- `requested_language` (text)
- `software` (object)
- `text_length` (number)
- `unreadable_count` (number)

**Example output**

```json
{
  "categories": [
    {
      "count": 1,
      "id": "TYPOS",
      "name": "Possible Typo"
    }
  ],
  "has_issues": true,
  "input_format": "text",
  "issue_count": 1,
  "issue_types": [
    {
      "count": 1,
      "id": "misspelling",
      "name": "misspelling"
    }
  ],
  "issues": [
    {
      "context": {
        "length": 5,
        "offset": 15,
        "text": "This is a test valeu."
      },
      "end_offset": 20,
      "length": 5,
      "message": "Possible spelling mistake found.",
      "offset": 15,
      "replacements": [
        "value",
        "valet",
        "veiled",
        "vale",
        "vales"
      ],
      "rule": {
        "category_id": "TYPOS",
        "category_name": "Possible Typo",
        "description": "Possible spelling mistake",
        "id": "MORFOLOGIK_RULE_EN_US",
        "issue_type": "misspelling",
        "sub_id": null,
        "urls": []
      },
      "sentence": "This is a test valeu.",
      "short_message": "Spelling mistake",
      "suggestion": "value",
      "text": "valeu",
      "verified": true
    }
  ],
  "language": {
    "base_code": "en",
    "code": "en-US",
    "detected_code": "en-US",
    "detected_name": "English (US)",
    "name": "English (US)"
  },
  "level": "default",
  "preferred_variants": [
    "en-US",
    "de-DE",
    "pt-BR",
    "ca-ES"
  ],
  "request_count": 1,
  "requested_language": "auto",
  "software": {
    "name": "LanguageTool",
    "premium": false,
    "version": "6.9"
  },
  "text_length": 21,
  "unreadable_count": 0
}
```

### Correct text

Proofread a text and get the corrected version back, ready to send. LanguageTool's own answer is a list of positions and suggestions; this applies them, from the end of the text backwards so nothing shifts, and reports every change it made with what it replaced and the other suggestions it passed over. Choose whether to fix everything, only real errors, or only spelling, and anything left alone comes back with the reason. No API key required.

**Inputs**

- Text (`text`, text, required): The text to check. Plain text by default; set Input format to HTML to check an email or a page body, and the tags are stepped over rather than reported as mistakes. A long text is checked in as many requests as it takes, 20,000 characters at a time (60,000 with a Premium connection), and comes back as one answer.
- Language (`language`, text): The language the text is written in, as a code such as en-US or de-DE. Leave it on Detect automatically for text arriving from somewhere else. LanguageTool only checks spelling when the variant is named, so 'en' and 'de' are not offered and are refused if typed: pick en-US or en-GB rather than English. Default: `auto`.
- Input format (`input_format`, text): Whether the text is plain prose or HTML. HTML is handed to LanguageTool as an annotated document, so tags, comments and entities are stepped over: 'caf&eacute;' is read as one word, and a heading does not run into the paragraph under it. One of: `text` (Plain text), `html`. Default: `text`.
- Fix (`apply`, text): Which issues to correct. Everything applies the first suggestion for every issue. Errors only leaves style, register and redundancy suggestions alone, which is what most writing wants. Spelling only touches nothing but misspellings and typography. Whatever is left alone is still reported, with the reason. One of: `all` (Everything), `correctness` (Errors only, not style), `spelling` (Spelling only). Default: `all`.
- Level (`level`, text): How strict to be. Picky turns on the extra rules LanguageTool describes as useful for formal text - typography, style and register - and finds more in a contract than in a chat message. One of: `default`, `picky`. Default: `default`.
- Writer's native language (`mother_tongue`, text): The writer's native language, which turns on LanguageTool's false-friend rules for some language pairs: a German speaker writing English gets told about 'become' for 'bekommen'. It is a fact about the writer, not about the text, so leave it empty unless you know it.
- Preferred variants (`preferred_variants`, text): Which variant to prefer when the language is detected, comma-separated, such as en-GB, de-AT. Detection can tell English from German but not British from American English, and LanguageTool checks no spelling until a variant is chosen, so en-US, de-DE, pt-BR, ca-ES are sent when this is empty. Only used when the language is detected automatically.
- Rules to ignore (`disabled_rules`, text): Rule IDs to turn off, comma-separated, such as UPPERCASE_SENTENCE_START, WHITESPACE_RULE. Every issue reported by this integration carries the ID of the rule that found it, so the way to silence a rule is to run the step once and paste the ID from what came back.
- Categories to ignore (`disabled_categories`, text): Whole categories to turn off, comma-separated, such as TYPOGRAPHY, STYLE, REDUNDANCY. Every issue carries its category ID, so run the step once and paste the ones you do not want.
- Personal dictionaries (`dictionaries`, text): The personal dictionaries to take words from, comma-separated, so the words in them stop being reported as misspellings. Needs a Premium connection; leave empty for the account's default dictionary.

**Outputs**

- `applied_count` (number)
- `apply` (text)
- `changed` (true/false)
- `changes` (list)
- `corrected_text` (text)
- `input_format` (text)
- `issue_count` (number)
- `language` (object)
- `level` (text)
- `request_count` (number)
- `skipped` (list)
- `skipped_count` (number)
- `software` (object)
- `text_length` (number)
- `unreadable_count` (number)

**Example output**

```json
{
  "applied_count": 1,
  "apply": "all",
  "changed": true,
  "changes": [
    {
      "after": "value",
      "alternatives": [
        "valet",
        "veiled",
        "vale",
        "vales"
      ],
      "before": "valeu",
      "category_id": "TYPOS",
      "issue_type": "misspelling",
      "length": 5,
      "message": "Possible spelling mistake found.",
      "offset": 15,
      "rule_id": "MORFOLOGIK_RULE_EN_US"
    }
  ],
  "corrected_text": "This is a test value.",
  "input_format": "text",
  "issue_count": 1,
  "language": {
    "base_code": "en",
    "code": "en-US",
    "detected_code": "en-US",
    "detected_name": "English (US)",
    "name": "English (US)"
  },
  "level": "default",
  "request_count": 1,
  "skipped": [],
  "skipped_count": 0,
  "software": {
    "name": "LanguageTool",
    "premium": false,
    "version": "6.9"
  },
  "text_length": 21,
  "unreadable_count": 0
}
```

### Detect the language

Work out which of LanguageTool's thirty-odd languages a text is written in, so a workflow can route a support ticket, pick a reply template or choose a translation target. One request, no API key, and only the opening of a long text is sent, so checking a whole document costs the same as checking a sentence. The answer carries both the full code, such as en-GB, and the plain language code, such as en, so a branch can match on either. No API key required.

**Inputs**

- Text (`text`, text, required): The text whose language to work out. Only the first 2,000 characters are sent, which is far more than detection needs. A single short sentence can be ambiguous between close languages; a paragraph rarely is.
- Preferred variants (`preferred_variants`, text): Which variant to prefer when the language is detected, comma-separated, such as en-GB, de-AT. Detection can tell English from German but not British from American English, and LanguageTool checks no spelling until a variant is chosen, so en-US, de-DE, pt-BR, ca-ES are sent when this is empty. Only used when the language is detected automatically.

**Outputs**

- `base_code` (text)
- `checked_as_code` (text)
- `checked_as_name` (text)
- `detected_code` (text)
- `detected_name` (text)
- `preferred_variants` (list)
- `sample_length` (number)
- `sampled` (true/false)
- `text_length` (number)

**Example output**

```json
{
  "base_code": "en",
  "checked_as_code": "en-US",
  "checked_as_name": "English (US)",
  "detected_code": "en-US",
  "detected_name": "English (US)",
  "preferred_variants": [
    "en-US",
    "de-DE",
    "pt-BR",
    "ca-ES"
  ],
  "sample_length": 21,
  "sampled": false,
  "text_length": 21
}
```

### List dictionary words

List the words in the account's personal dictionaries - the product names, people and house spellings LanguageTool has been told to stop flagging. Use it to review what is in a dictionary before adding to it, or to copy one workspace's list into another. Needs a LanguageTool Premium username and API key on the connection.

**Inputs**

- Dictionaries (`dictionaries`, text): Which dictionaries to take words from, comma-separated. Leave empty for the account's default dictionary.
- Number of words (`limit`, number): How many words to return, from 1 to 1,000. Defaults to 100; LanguageTool's own default is 10, which is a page rather than a dictionary. A personal dictionary holds up to 500 words. From 1 to 1000.
- Skip (`offset`, number): How many words to skip before the first one returned, for reading a long dictionary a page at a time. Defaults to 0. At least 0.

**Outputs**

- `dictionaries` (list)
- `has_more` (true/false)
- `limit` (number)
- `offset` (number)
- `word_count` (number)
- `words` (list)

**Example output**

```json
{
  "dictionaries": [],
  "has_more": false,
  "limit": 100,
  "offset": 0,
  "word_count": 3,
  "words": [
    "Lodol",
    "Skipflow",
    "webhook"
  ]
}
```

### List languages

List every language and variant LanguageTool can check, each with the code the other steps take. Use it to see what is available, or to check that a language a workflow was handed is one LanguageTool knows before sending it a document. The list is the service's own and is fetched live, so a language added upstream appears here. No API key required.

**Inputs**: None.

**Outputs**

- `language_count` (number)
- `languages` (list)
- `variant_count` (number)

**Example output**

```json
{
  "language_count": 3,
  "languages": [
    {
      "code": "en",
      "is_variant": true,
      "long_code": "en-US",
      "name": "English (US)"
    },
    {
      "code": "de",
      "is_variant": true,
      "long_code": "de-DE",
      "name": "German (Germany)"
    },
    {
      "code": "fr",
      "is_variant": false,
      "long_code": "fr",
      "name": "French"
    }
  ],
  "variant_count": 2
}
```

### Remove a dictionary word

Remove one word from a personal dictionary, so LanguageTool goes back to reporting it. Removing the last word of a dictionary deletes the dictionary itself. A word that was not there is reported as such rather than failing, so the step is safe to re-run. Needs a LanguageTool Premium username and API key on the connection.

**Inputs**

- Word (`word`, text, required): The word to remove, spelled as it was added. A single word, not a phrase.
- Dictionary (`dictionary`, text): Which personal dictionary to remove it from. Leave empty for the account's default one.

**Outputs**

- `dictionary` (text)
- `removed` (true/false)
- `was_absent` (true/false)
- `word` (text)

**Example output**

```json
{
  "dictionary": null,
  "removed": true,
  "was_absent": false,
  "word": "Lodol"
}
```
