# eslint-plugin-string-to-lingui

ESlint plugin to check if all strings are translated

## Installation

You'll first need to install [ESLint](http://eslint.org):

```
$ yarn add eslint --dev
```

Next, install `eslint-plugin-string-to-lingui`:

```
$ yarn add eslint-plugin-string-to-lingui --dev
```

**Note:** If you installed ESLint globally (using the `-g` flag) then you must also install `eslint-plugin-string-to-lingui` globally.

## Usage

Add `string-to-lingui` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix:

```json
{
  "plugins": ["string-to-lingui"]
}
```

Then configure the rules you want to use under the rules section.

```json
{
  "rules": {
    "string-to-lingui/missing-lingui-transformation": 2,
    "string-to-lingui/t-call-in-function": 2,
    "string-to-lingui/macro-inside-t-and-i18": 2,
    "string-to-lingui/t-should-be-before-macro": 2,
    "string-to-lingui/no-single-varibles-to-translate": 2,
    "string-to-lingui/check-en-messages: [1, {
        "sourcePath": "node_modules/@pleo-io/product-web-translations/en/messages.json",
        "similarityThreshold": 0.9,
        "maxSuggestions": 3
    }],
    "string-to-lingui/text-restrictions": [
      2,
      {
        "rules": [
          {
            "patterns": ["''", "’", "“"],
            "message": "Error message"
          }
        ]
      }
    ],
    "string-to-lingui/forbid-i18n-calls": [
      2,
      {
        "rules": [
          {
            "handlerName": "_",
            "message": "Use t`` from '@lingui/macro' instead"
          },
          {
            "handlerName": "number",
            "message": "Use formatCurrency or formatNumber instead"
          }
        ]
      }
    ]
  }
}
```

## Supported Rules

## missing-lingui-transformation

Check that code doesn't contain strings/templates/jsxText what should be wraped into `<Trans>` or `i18n`

### Options

#### ignore

The `ignore` option specifies exceptions not to check for
literal strings that match one of regexp paterns.

Examples of correct code for the `{ "ignore": ["rgba"] }` option:

```jsx
/*eslint string-to-lingui/missing-lingui-transformation ["error", {"ignore": ["rgba"]}]*/
const a = <div color="rgba(100, 100, 100, 0.4)"></div>;
```

#### ignoreFunction

THe `ignoreFunction` option speficies exceptions not check for
function calls whose names match one of regexp patterns.

Examples of correct code for the `{ "ignoreFunction": ["showIntercomMessage"] }` option:

```js
/*eslint string-to-lingui/missing-lingui-transformation: ["error", { "ignoreFunction": ["showIntercomMessage"] }]*/
const bar = showIntercomMessage("Please, write me");
```

#### ignoreAttribute

The `ignoreAttribute` option specifies exceptions not to check for JSX attributes that match one of ignored attributes.

Examples of correct code for the `{ "ignoreAttribute": ["style"] }` option:

```jsx
/*eslint string-to-lingui/missing-lingui-transformation: ["error", { "ignoreAttribute": ["style"] }]*/
const element = <div style={{ margin: "1rem 2rem" }} />;
```

## t-call-in-function

Check that `t` calls are inside `function`. It is necessary for language switching.

## i18n-number-call-in-function

Check that `i18n.number` calls are inside `function`. It is necessary for language switching.

## i18n-only-identifiers

Check that t`` doesn't contain member or function expressions like t`\${obj.prop} or t`func()`

## check-en-messages

Checks similar messages from the source and give suggestions for replacement

## forbid-i18n-calls

Check that `i18n.*` is not used at all. For now, it is needed to prevent `i18n._` and `i18n.number`.
`i18n._` is not needed because with lingui@v3+ it is working incorrectly (Messages are not extracted) `t` from `macro` should be used instead. `i18n.number`is not needed because we create handlers `formatCurrency` and `formatNumber`

## macro-inside-t-and-i18

Check that macro calls: [`number`,`date`] are inside `t` which is inside `i18n` call. It is necessary for `macro` to be working correctly.

## t-should-be-before-macro

Check that `t` is imported from `@lingui/macro` before `number` or `date`

## no-single-varibles-to-translate

Doesn't allow single variables without text to translate like <Trans>{variable}</Trans> or t`${variable}`

## text-restrictions

Check that strings/templates/jsxText doesn't contain patterns from the rules

### Options

### rules

`rules` is array of rules when one rule has structure `{ "patterns": ["first", "second"], "message": "error message" }`.

each `rule` has a structure:

- `patterns` is an array of regex or strings
- `message` is a error message that will be displayed if restricting pattern matches text
- `flags` is a string with regex flags for patterns
- `isOnlyForTranslation` is a boolean indicating that patterns should be found only inside `Trans` tags or `t` tagged template

## no-dynamic-keys

Doesn't allow dynamic keys for i18n.t

```js
// nope ⛔️
i18n.t(hello);

// ok ✅
i18n.t("hello");
```

## no-linebreaks

Doesn't allow linebreaks (`\r` or `\n` or both) in messages to be translated with `t` macro e.g:

```js
// nope ⛔️
t`foo\n`;

t`foo
bar`;

// ok ✅
t`foo bar`;
```

## no-tags-in-trans

Ensures `<Trans></Trans>` isn't wrapping a single element unnecessarily

```jsx
// nope ⛔️
<Trans><strong>Foo bar</strong></Trans>

// ok ✅
<strong><Trans>Foo bar</Trans></strong>
```
