# Custom Spellchecker

This module allows you to add custom spellcheckers to verify translations against specific rules that are not supported by default.

[Custom Spellchecker Module](https://support.crowdin.com/developer/crowdin-apps-module-custom-spellchecker/)

## Sample

```js ins="customSpellchecker" title="index.js"
    import crowdinModule from '@crowdin/app-project-module';

    const configuration = {
      baseUrl: 'https://123.ngrok.io',
      clientId: 'clientId',
      clientSecret: 'clientSecret',
      name: 'Sample App',
      identifier: 'sample-app',
      description: 'Sample App description',
      dbFolder: import.meta.dirname,
      imagePath: import.meta.dirname + '/logo.png',
      customSpellchecker: [
        {
          getSupportedLanguage: async ({ client, context }) => {
            return [
              {
                code: 'en',
                name: 'English'
              },
              {
                code: 'uk',
                name: 'Ukrainian'
              }
            ];
          },
          runSpellCheck: async ({ client, context, language, texts }) => {
            // language = 'en';
            // texts = [ 'I have an appple', 'And many oranges' ];
            // some spelling logic
            return {
              texts: [
                {
                  text: 'I have an appple',
                  matches: [
                    {
                      category: 'typos',
                      message: 'Found a grammar error',
                      shortMessage: 'Grammar error',
                      offset: 10,
                      length: 6,
                      replacements: [
                        'apple'
                      ]
                    }
                  ]
                },
                {
                  text: 'And many oranges',
                  matches: []
                }
              ]
            }
          }
        }
      ]
    };

    crowdinModule.createApp(configuration);
    ```
  ```ts ins="customSpellchecker" title="index.ts"
    import crowdinModule from '@crowdin/app-project-module';
    import type { ClientConfig } from '@crowdin/app-project-module';

    const configuration: ClientConfig = {
      baseUrl: 'https://123.ngrok.io',
      clientId: 'clientId',
      clientSecret: 'clientSecret',
      name: 'Sample App',
      identifier: 'sample-app',
      description: 'Sample App description',
      dbFolder: import.meta.dirname,
      imagePath: import.meta.dirname + '/logo.png',
      customSpellchecker: [
        {
          getSupportedLanguage: async ({ client, context }) => {
            return [
              {
                code: 'en',
                name: 'English'
              },
              {
                code: 'uk',
                name: 'Ukrainian'
              }
            ];
          },
          runSpellCheck: async ({ client, context, language, texts }) => {
            // language = 'en';
            // texts = [ 'I have an appple', 'And many oranges' ];
            // some spelling logic
            return {
              texts: [
                {
                  text: 'I have an appple',
                  matches: [
                    {
                      category: 'typos',
                      message: 'Found a grammar error',
                      shortMessage: 'Grammar error',
                      offset: 10,
                      length: 6,
                      replacements: [
                        'apple'
                      ]
                    }
                  ]
                },
                {
                  text: 'And many oranges',
                  matches: []
                }
              ]
            }
          }
        }
      ]
    };

    crowdinModule.createApp(configuration);
    ```
  ## Configuration

The custom spellchecker application requires implementation of two functions to work properly.

### `getSupportedLanguage` Function

Called when retrieving the list of languages supported by the custom spellchecker.

#### Parameters

- `client` - Crowdin API client.
- `context` - [Context object](/app-project-module/reference/context/).

#### Return Value

An array of objects with the following structure:

```yml
{
  code: string,
  name: string
}
```

### `runSpellCheck` Function

Called when running the spellchecker against the provided texts.

#### Parameters

- `client` - Crowdin API client.
- `context` - [Context object](/app-project-module/reference/context/).
- `language` - Language code.
- `texts` - Array of texts to check.

#### Return Value

It should return an object with the following structure:

```yml
{
  texts: [
    {
      text: string,
      matches: [
        {
          category: string,
          message: string,
          shortMessage: string,
          offset: number,
          length: number,
          replacements: string[]
        }
      ]
    }
  ]
}
```

**Caution:** The `runSpellCheck` function must return all texts that were received in the incoming request.

Read more about available [categories](https://support.crowdin.com/developer/crowdin-apps-module-custom-spellchecker/#expected-response-from-the-app-with-spelling-issues).

### Multiple Spellcheckers

You can register multiple custom spellcheckers in a single app by providing an array:

```js title="index.js"
const configuration = {
  // ... other configuration
  customSpellchecker: [
    {
      name: 'Spellchecker A',
      getSupportedLanguage: async () => [{ code: 'en', name: 'English' }],
      runSpellCheck: async ({ texts }) => ({
        texts: texts.map((text) => ({ text, matches: [] }))
      })
    },
    {
      name: 'Spellchecker B',
      getSupportedLanguage: async () => [{ code: 'de', name: 'German' }],
      runSpellCheck: async ({ texts }) => ({
        texts: texts.map((text) => ({ text, matches: [] }))
      })
    }
  ]
};
```