Make valid-i18n-keys rule strict and fix most exceptions

This commit is contained in:
Jamie Kyle
2023-03-29 10:15:54 -07:00
committed by GitHub
parent 18a6da310f
commit 11cfcb4e32
36 changed files with 796 additions and 687 deletions

View File

@@ -14,9 +14,11 @@ const messagesCacheKey = hashSum.digest('hex');
function isI18nCall(node) {
return (
node.type === 'CallExpression' &&
node.callee.type === 'Identifier' &&
node.callee.name === 'i18n'
(node.type === 'CallExpression' &&
node.callee.type === 'Identifier' &&
node.callee.name === 'i18n') ||
(node.callee.type === 'MemberExpression' &&
node.callee.property.name === 'i18n')
);
}
@@ -36,20 +38,7 @@ function valueToMessageKey(node) {
if (isStringLiteral(node)) {
return node.value;
}
if (node.type !== 'TemplateLiteral') {
return null;
}
if (node.quasis.length === 1) {
return node.quasis[0].value.cooked;
}
const parts = node.quasis.map(element => {
return element.value.cooked;
});
return new RegExp(`^${parts.join('(.*)')}$`);
return null;
}
function getI18nCallMessageKey(node) {
@@ -80,24 +69,11 @@ function getIntlElementMessageKey(node) {
let value = idAttribute.value;
if (value.type === 'JSXExpressionContainer') {
value = value.expression;
}
return valueToMessageKey(value);
}
function isValidMessageKey(key) {
if (typeof key === 'string') {
if (Object.hasOwn(messages, key)) {
return true;
}
} else if (key instanceof RegExp) {
if (messageKeys.some(k => key.test(k))) {
return true;
}
}
return false;
return Object.hasOwn(messages, key);
}
module.exports = {

View File

@@ -27,27 +27,68 @@ ruleTester.run('valid-i18n-keys', rule, {
options: [{ messagesCacheKey }],
},
{
code: 'i18n(`AddCaptionModal__${title}`)',
code: `window.i18n("AddCaptionModal__title")`,
options: [{ messagesCacheKey }],
},
{
code: `let jsx = <Intl id="AddCaptionModal__title"/>`,
options: [{ messagesCacheKey }],
},
],
invalid: [
{
code: 'i18n(`AddCaptionModal__${title}`)',
options: [{ messagesCacheKey }],
errors: [
{
message: "i18n()'s first argument should always be a literal string",
type: 'CallExpression',
},
],
},
{
code: 'window.i18n(`AddCaptionModal__${title}`)',
options: [{ messagesCacheKey }],
errors: [
{
message: "i18n()'s first argument should always be a literal string",
type: 'CallExpression',
},
],
},
{
code: `let jsx = <Intl id={"AddCaptionModal__title"}/>`,
options: [{ messagesCacheKey }],
errors: [
{
message:
"<Intl> must always be provided an 'id' attribute with a literal string",
type: 'JSXOpeningElement',
},
],
},
{
code: 'let jsx = <Intl id={`AddCaptionModal__title`}/>',
options: [{ messagesCacheKey }],
errors: [
{
message:
"<Intl> must always be provided an 'id' attribute with a literal string",
type: 'JSXOpeningElement',
},
],
},
{
code: 'let jsx = <Intl id={`AddCaptionModal__${title}`}/>',
options: [{ messagesCacheKey }],
errors: [
{
message:
"<Intl> must always be provided an 'id' attribute with a literal string",
type: 'JSXOpeningElement',
},
],
},
],
invalid: [
{
code: `i18n("THIS_KEY_SHOULD_NEVER_EXIST")`,
options: [{ messagesCacheKey }],