GithubHelp home page GithubHelp logo

edvardchen / eslint-plugin-i18next Goto Github PK

View Code? Open in Web Editor NEW
128.0 128.0 39.0 1.02 MB

ESLint plugin for i18next. Prevent to display non-localized text for users

License: MIT License

JavaScript 98.33% TypeScript 1.67%

eslint-plugin-i18next's People

Contributors

darcros avatar dependabot[bot] avatar edvardchen avatar efim-kapliy avatar emroussel avatar fibo avatar jeffreyatw avatar joshuat avatar juan-cortes avatar lgenzelis avatar mathieutu avatar megos avatar nickskotny avatar qluxzz avatar ramijarrar avatar tgds avatar zubb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

eslint-plugin-i18next's Issues

How to ignore test files?

test.each`
  firstName     | lastName                 | userName    | expected
  ${"John"} | ${"Doe"} | ${"johhnie"} | ${"John Doe(johhnie)"}

I have test file with spec like above (jest), how to ignore gloabally checking it?

Add checkAttribute option

Instead of linting every possible JSX attribute and using ignoreAttribute to allow only certain attributes, it would be great to be able to flip the logic and be able to check only certain attributes (string or regex) and ignore others. The signal:noise ratio on some of the errors produced is pretty low, and our ignoreAttribute list is getting very long. Example config:

checkAttribute:
  - /placeholder.*/i
  - /heading.*/i
  - /text.*/i
  - /label.*/i

Thank you for your amazing work on this useful plugin.

Error: Failed to load plugin 'i18next' declared in '.eslintrc': Cannot find module 'typescript'

The latest release (4.3.0) has a reference to require('typescript') on line 12 of lib/rules/no-literal-string.js, but typescriptisn't listed as adependencyorpeerDependencyin the package, so doesn't get added to (or sourced from) the project alongside it during installation. Had to install4.2.0` instead, because I didn't want to add typescript to my project just for an eslint plugin.

Add option to ignore custom static class properties?

Using displayName strings in react class components is a common pattern (especially when using higher order components).

const withForm = () => WrappedComponent => {
    const componentName = WrappedComponent.displayName || WrappedComponent.name;

    class Form extends Component {
        static displayName = `withForm(${componentName})`;

        // ...
    }
}

However, this plugin flags displayName as an error since it uses an unwrapped string. It can be fixed by abstracting it into a constant like this:

const withForm = () => WrappedComponent => {
    const componentName = WrappedComponent.displayName || WrappedComponent.name;

    const DISPLAY_NAME = `withForm(${componentName})`;

    class Form extends Component {
        static displayName = DISPLAY_NAME;

        // ...
    }
}

but it would be nice to be able to keep it in its original form for simplicity and cleanliness.

Do you feel like it's a decent/common enough use case to justify adding a new option to ignore a list of custom static class properties? If yes, happy to open a PR to add this if you point me in the right direction.

Support regex test for string literal

We are a team developing products that using CJK characters for UI display. We don't care other string literals that using English because they are not likely to be displayed. Especially we are trying to use this rule to scan how many strings need to be translated in our codebase. Having a regex to test if the string is CJK included will help us exclude most valid cases from false positive.

Add an option to ignore color strings

Add an option to ignore hex color strings.

For example:

{ ignoreColors: true }

This would ignore color strings like:

"#aaa"
"#aaaa"
"#ababab"
"#abababab"
"rgb(123, 123, 123)"
"rgba(123, 123, 123, 123)"
"hsl(...)"

These strings are not translatable anyways.

Allow ignoring all attributes

It would be nice to have an explicit way to ignore all attributes as all attribute warnings have been false positives for me so far. Currently I use:

        'i18next/no-literal-string': [
            'error',
            { markupOnly: true, onlyAttribute: [""] },
        ],

But that's a rather confusing way of configuring this in my opinion.

Bug [no-literal-string]: specifying `\u003F` quits the plugin.

I have the problem that characters such as "!" and "?" are not filtered. Even when I specify them in the exclude option, it does not work. Which means things like

 disallow literal string: <button type="button" onClick={() => onSubmit && onSubmit(formFields)} disabled={!valid}>
                    {t('submit')}!
                </button>  i18next/no-literal-string

are still seen as errors.

I tried around a bit and for some reason my errors are gone when I specify \u003F (the unicode character for ?) in the exclude options.

 "rules": {
                "i18next/no-literal-string": [2, { "words": { "exclude": ["\u003F"] } }]
            }

Can those characters be ignored by default? Many of those can not be excluded.

Support -fix and add 'replace' option

The idea is if we try to internationalize the existing app, we'll see a lot of errors, which at the first glance can be easily fixed automatically.
My suggestion is to add a property replaceFnName or something like this and make the rule fixable.

Example:
Option replaceFnName is equal to i18nex.t

JSX text:

//incorrect
<div foo="foo"></div>
<div foo={"foo"}></div>

after eslint -fix

<div foo={ i18nex.t('foo', 'foo') }></div>
<div foo={ i18nex.t('foo', 'foo') }></div>

@edvardchen what do think? I can create PR if you find this idea interesting

Erroneously flagging literal case inside JSX in jsx-only mode

In JSX-only mode, this raises a disallow literal string error for the line case 'abc':

<div>{[].map((a) => {
  switch (a) {
    case 'abc':
      return null;
    default:
      return null;
  }
})}</div>

Expected behavior: This nested JS expression should be evaluated as JS

Does not check nested function calls

Hi there. I've noticed this plugin does not check function calls that are more than 1 level deep, for example:

import "./styles.css";
import React, { useEffect } from "react";

function t() {
  //
}

function action() {
  //
}

function dispatch() {
  //
}

export default function App() {
  useEffect(() => {
    action("hello"); // shows error
    dispatch(action("hello")); // does not show error
  });
  return <div className="App">{t("foo")}</div>;
}

Screenshot:

Screenshot 2021-03-05 at 06 55 59

I've attached an archive of a small project (downloaded from codesandbox) that shows the error:

y9dzx (1).zip

Is there any way I can configure the plugin to check the function call dispatch(action("hello"));? In this case I'm using redux dispatch to add an error message to the store and would like to get the action payload validated.

Can't ignore "&ndash;"

I've been trying to ignore the string &ndash; but the rule doesn't seem to be working for it. I've used this rule:
"i18next/no-literal-string": [ 2, { "words": { exclude: ["&ndash;", "Option"] } } ]

With this rule the Option gets ignored fine inside a span element, but &ndash; inside span doesn't get ignored. As far as I know the & and ; don't have a special meaning in regex so it should work as is. Is this a bug or am I doing something wrong?

Another way to ignore attributes of DOM

For native DOM elements, instead of appending more ”allowed“ attributes, should we ignore all attributes but just check some attributes like "placeholder" ?

There are very few attributes of native DOM elements that can be displayed to user.

Ignore value of property regardless of its type (array of string should be ignored)

When I set ignoreProperty I expect that all values would be ignored, no matter what type it has. Currently, it seems that only string value is ignored. But when ignoredProperty has an array of strings, then these strings are validated.

My config:

ignoreProperty: ['animation']

This code works:

const iconStyles: SxStyleProp = {
  animation: 'flightMove 4s infinite
};

This code fails:

const iconStyles: SxStyleProp = {
  animation: ['flightMove 4s infinite', 'flightMove 5s infinite']
};

Ignore files

Hello
Is it possible to add ignore option for files? For example to turn off validation for all stories files. (eg. file name Counter.stories.tsx)

Thanks

next release?

So excited for version 5.2.1! To be able to customize the message is awesome!
I see it hasn't shown up on npm yet -- soon?? soon?

Thank you!

Clarify new version documentation

I've just upgraded to the new version - it's great!

I found the documentation of the new configuration a bit confusing, although it made more sense because I was familiar with the old config.

For selectors,

  • words controls plain text
  • jsx-components controls JSX elements
  • jsx-attributes controls JSX elements' attributes
  • callees controls function calls
  • object-properties controls objects' properties
  • class-properties controls classes' properties

From this, it wasn't clear that words controls the actual content of the literal string, whereas the others all control where they are used.

Maybe it would be clearer with examples?

  • words decides whether literal strings are allowed (in any situation), based on the content of the string
  • jsx-components decides whether literal strings as children within a component are allowed, based on the component name
    e.g. by default, Trans is excluded, so "Hello World" in the following is allowed.
<Trans i18nKey="greeting">Hello World</Trans>
  • jsx-attributes decides whether literal strings are allowed as JSX attribute values, based on the name of the attribute
    e.g. if data-testid is excluded, "important-button" in the following is allowed
<button data-testid="important-button" onClick={handleClick}>{t('importantButton.label')}</button>
  • callees decides whether literal strings are allowed as function arguments, based on the identifier of the function being called
    e.g. if window.open is excluded, "http://example.com" in the following is allowed
window.open('http://example.com')

callees also covers object constructors, such new Error('string') or new URL('string').

  • object-properties decides whether literal strings are allowed as object property values, based on the property key
    e.g. if fieldName is excluded but label is not, "currency_code" is allowed but "Currency" is not:
const fieldConfig = {
  fieldName: 'currency_code',
  label: 'Currency'
}

Ignore accessibilityRole and similar attributes

The plugin is (by default) way to aggressive in its suggestions to translate strings.
Our list of ignores is already quite extensive (I have removed non-standard only for our app related things):

ignoreCallee: [
          "navigate",
          "replace",
          "create",
          "it",
          "only",
          "describe",
          "mock",
          "openURL",
          "toLocaleDateString",
          "watch",
          "addListener",
          "removeListener",
          "console.log",
          "getFileName",
          "toLocaleString",
          "console.error",          
          "readFile",
        ],
        ignoreProperty: [
          "id",
          "image",
          "key",
          "style",
        ],
        ignoreAttribute: [
          "color",
          "icon",
          "uri",
          "attachment",
          "resizeMode",
          "ellipsizeMode",
          "keyboardType",
          "name",
          "initialRouteName",
          "labelAlignment",
          "navigate",
          "id",
          "image",
          "pointerEvents",
          "preserveAspectRatio",
          "onChange",
          "mode",
          "date",
          "clearButtonMode",
          "size",
          "selected",
          "resizeMethod",
          "identifier",
          "testID",
          "autoCapitalize",
          "returnKeyType",
          "decelerationRate",
          "snapToAlignment",
          "keyboardShouldPersistTaps",
          "presentationStyle",
          "textContentType",
          "autoCompleteType",
          "blurType",
          "keyboardDismissMode",          
        ],

Maybe there is a way to somehow limit the number of ignores one has to provide?

Whitespace around excluded words

I have indented jsx like this:
return (
<div className="alert alert-danger" role="alert">
{t("No user details were found")}!
</div>
)

The plugin complains about the exclamation point. When I try to exclude it with "words": { exclude: ["!"] } the warning doesn't go away. If I remove the indentations in the jsx then the warning goes away. I had to add this to eslintrc: "words": { exclude: ["!\s*"] } to ignore all whitespace after the exclamation point created by the indentation in order to get rid of the warning.

I think the plugin should ignore all whitespace at least created by indentation if not all whitespace.

How to use global markupOnly option?

I have a configuration problem ... not being eslint expert
... I don't know how/where in .eslintrc.js it has to be defined.

I work with react/JSX using f.e. css in js - literal values gives false positives, too.
Is there a possibility to define ignoreAttribute option globally (.eslintrc.js), not per line?

Entire `switch` case missed if testing string literal

I think this is caused by the fix for #2 , where switch cases statements with a literal test cause the entire block to be skipped. I have code like this that I'd like to fail the linter, but I don't quite see how to fix it and still keep #2 intact.

e.g. this title assignment shouldn't be allowed:

    switch (task.state) {
        case kTaskState_InProgress:
            style = classes.inProgress;
            title = "In Progress"
            break;

Thanks!

Does not identify html issues

In my Angular 13 project I am running eslint-plugin-i18next 6.0.0-2. When I configure the mode to 'all' the untranslated strings in typescript files are successfully identified. However, it is unable to identify issues in html files.

Support for curried functions

Example curried function from React MUI styled components

import { styled } from '@mui/system';

const MyComponent = styled('div')((theme) => ({
  color: 'darkslategray',
  backgroundColor: 'aliceblue',
  padding: 8,
  borderRadius: 4,
}));

Adding the eslint rule ignoreCallee: ["styled"] ignores the div string but does not ignore the darkslategray

JSX nodes/attributes only?

Thank you for the wonderful plugin!

I was wondering whether there's any support for an option or rule that targets only JSX nodes/attributes and ignores all other string literals:

import { MyOtherComponent } from "./my-other-component";

const MyComponent = () => {
  const foo = "Foo"; // no violation
  return (
    <MyOtherComponent bar="Bar">{/* violation - string literal in a JSX prop */}
      Baz {/* violation - undecorated JSX text node */}
    </MyOtherComponent>
  );
};

Bug: template literals are being ignored

The plugin correctly processes single-quoted and double-quoted strings, such as:

'Hello' // warning
"Hello" // warning

but wrongly ignores template literals:

`Hello` // no warning

Template literals are often allowed in internationalization packages and even if not, they might as well be equivalent to normal strings (i.e. to not contain substitution).

Please consider adding the processing of template literals.

Excluded words are not compared case insensitive.

With i18next/no-literal-string excluded words are not case insensitively excluded. That is, if I exclude "Ok", words like "OK" and "ok" are still treated as errors.

I don't think the goal of this rule should be to detect typos (or else should be moved to a different rule), so it would be better to exclude them case insensitive.

Ignore symbols

Are there any way to ignore symbols. If I do this:

'i18next/no-literal-string': [
  'error',
  { words: { exclude: ['('] } },
]

I get this error:
SyntaxError: Invalid regular expression: /(^|\.)($/: Unterminated group

Same error if I try to escape it:
{ words: { exclude: ['\('] } },

Some strings should not be checked

I found this plugin really useful, there are some cases where it complains about strings that should not be checked,

for example:

document.addEventListener('click', () => {})

or also:

<svg id='my-icon' viewbox='0 0 32 36' />

If somebody can give me some hint where to start I can try providing a pull request.

How to ignore constructor parameters?

Like this case:

throw new Error('some error message');

We do not throw error to users so this text should be ignored. But ignoreCallee seems not working with constructor.

ignore i18next t() by default

By default, i18next/no-literal-string will raise errors on strings given to the t() function from react hook useTranslation, which is confusing:

Current fix is to add t to the ignoreCallee list

rules:
   i18next/no-literal-string: ["error", { "ignoreCallee": ["cn", "t"] }]

Add ignoreAttribute option

I am using this plugin with React and Typescript and I have found it very useful so far.
However, I think it would be useful to add an ignoreAttribute option, similar to ignoreCallee but for JSX attributes.

The reason is:

<TextField
  variant="outlined"
  margin="normal"
  name="newEmail"
  autoComplete="email"
/>

TextField from material-ui

In the example above variant and margin are not reported as errors because their types are defined as a an union type of different strings.
But name and autocomplete are of type string so they get reported.

An ignoreAttribute option is necessary because the other solution would be spamming every file with eslint-disable-next-line comments.
And adding other attributes to the whitelist (like has been done with #4) for every framework and library that comes along would just be unfeasible.

I could work on the PR myself, just need to know if you would merge it.

Allow regex patterns in ignore lists

Add capability to add regex patterns along with strings in ignore lists.

For example, if I want to ignore all functions starting with "foo" (e.g. "foo()", "foo1()", "fooTwo()") and a function "bar()", I would add:

{ ignoreCallee: [/foo.*/, 'bar'] }

This would allow non-exhaustive checks, that is, to ignore a list of items where elements are not known in advance (or tedious to enumerate).

Related to #18 (the code will probably be shared)

Should ignore `declare module`

It seems the plugin currently flags this as an error:

declare module 'country-emoji' {
  export function flag(code: string): string;
}
module "country-emoji"
disallow literal stringeslint(i18next/no-literal-string)

missing lodash dependency

I am trying to include your plugin in a project with eslint through the pre-commit tool, but as you use the lodash dependency in your code and it is not specified in your direct dependencies it fails me because I have to include it manually.

I would like you to include this lodash dependency directly in your package.json instead of relying it from third party dependencies.

Check fails in function chaining

export const validationSchema = Yup.object({
  email: Yup.string()
    .email('1')
    .required('2'),
})

Error raised for 2, but not 1

await Auth.forgotPassword(email)
  .then(() => {
    showSuccessNotification({ title: '1' })
  })
  .catch((error) => {
    showErrorNotification({
      title: `2`,
    })
  })

Error raised for 2, not 1

export const validationSchema = Yup.object({
  code: Yup.string().required('1'),
  password: Yup.string()
    .required('2')
    .min(8, '3')
    .matches(/[0-9]/, '4')
    .matches(/[A-Z]/, '5')
    .matches(/[!@#$%^&*(),.?":{}|<>]/, '6'),
  confirmPassword: Yup.string()
    .oneOf([Yup.ref('password')], '7')
    .required('8'),
})

Errors raised for 1, 6, 8 not for others

Configuration is :

    "i18next/no-literal-string": ["error",
      {
        "ignoreCallee": [
          "console.log", "console.warn", "console.error",
          "document.querySelector", "gtag", "useField"
        ],
        "validateTemplate": true,
        "ignoreAttribute": [
          "autoComplete",
          "data-testid",
          "testId",
          "containerClasses",
          "contentClasses",
          "buttonWrapperClasses",
          "buttonClasses",
          "declineButtonClasses",
          "role", "href", "target",
          "inputVariant", "dataKey"
        ]
      }
    ]

Edit : after thinking, it seems only the last string is checked in a function chaining

Support ignoring default argument values

Didn't find a config option to allow default argument values:

function test(value = 'default value') {
  return value;
}

The only solution is to use create a UPPER_CASED variable and use it as the default value:

const DEFAULT_VALUE = 'default value'
function test(value = DEFAULT_VALUE) {
  return value;
}

This works but increases the code. Imagine, how it works if we have several string arguments with default values.

Ignoring a path in no-literal-string

It would be nice if I could ignore a path for the no-literal-string rule. For instance, I want to ignore **/*.test.tsx in my project since they are not actual code that is used in production. So I should be able to add literal strings in my test files.

Linter doesn't seem to catch hardcoded strings if using backticks

We've noticed if a hardcoded string is used, but with backticks, the linter doesn't catch it as being a hardcoded string.

e.g.

Caught
<Text>{booleanTest ? "Foo" : "Bar"}</Text>

Uncaught
<Text>{booleanTest ? `Foo ${bar}` : `Baz ${zip}`}</Text>

Thanks.

Support for UPPER_CASE arrays

Is there a way to ignore array constants with UPPER_CASE names?

Example:

const MY_ARRAY = [
  'foo',
  'bar',
  'baz'
];

The above will trigger the lint warning/error. Is this by design? Any plans to support ignoring arrays as well?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.