edvardchen / eslint-plugin-i18next Goto Github PK
View Code? Open in Web Editor NEWESLint plugin for i18next. Prevent to display non-localized text for users
License: MIT License
ESLint plugin for i18next. Prevent to display non-localized text for users
License: MIT License
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?
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.
Hi, thanks for this plugin.
The code allows passing regexp in include or exclude (for example).
However, the rules options are validated against the json schema, and it only allows string.
Would you be open to a change?
Thanks.
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 a
dependencyor
peerDependencyin the package, so doesn't get added to (or sourced from) the project alongside it during installation. Had to install
4.2.0` instead, because I didn't want to add typescript to my project just for an eslint plugin.
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.
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 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.
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.
I see in our project
<div>{t('something')}</div>
And I consider it as bad practice. Can linter mark it as error somehow?
You may not be aware of this, but legally, without a license, no one can use your code.
http://opensource.stackexchange.com/q/1720/775
Please add a license.
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.
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
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
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:
I've attached an archive of a small project (downloaded from codesandbox) that shows the error:
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.
I've been trying to ignore the string – but the rule doesn't seem to be working for it. I've used this rule:
"i18next/no-literal-string": [ 2, { "words": { exclude: ["–", "Option"] } } ]
With this rule the Option gets ignored fine inside a span element, but – 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?
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.
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']
};
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
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!
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 textjsx-components
controls JSX elementsjsx-attributes
controls JSX elements' attributescallees
controls function callsobject-properties
controls objects' propertiesclass-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 stringjsx-components
decides whether literal strings as children within a component are allowed, based on the component nameTrans
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 attributedata-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 calledwindow.open
is excluded, "http://example.com" in the following is allowedwindow.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 keyfieldName
is excluded but label
is not, "currency_code" is allowed but "Currency" is not:const fieldConfig = {
fieldName: 'currency_code',
label: 'Currency'
}
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?
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.
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?
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!
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.
I would like to request this change so that dispatch functions calls are not ignored by default. This is referring to https://github.com/edvardchen/eslint-plugin-i18next/blob/main/lib/rules/no-literal-string.js#L112.
Since we have no way to control this array that I am aware of I had to make a fork and remove it for my use case.
What do you think about this? Could we add some config options to have control over popularCallee array?
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
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>
);
};
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.
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.
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: ['\('] } },
"table": Object {
"addOnes": Object {
- "totalCount": "ValidMessage<String>",
+ "totalCount": "String('total {{0}}cases') ===> Expected argNameOrNumber but '{' found.",
},
},
which is valid in i18n-react's string interpolation syntax, marked as argNameOrNumber
error here
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.
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.
let text: string;
if (someBool) {
text = 'hello';
} else {
text = 'world';
}
The above code have no error emitted when lint with this plugin.
is there any way to ignore / whitelist switch case statements?
it is adding i18next.t even when I have already t('myKey')
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.
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)
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)
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.
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
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.
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.
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.
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?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.