lib/rules/i18n-no-reference.js (63 lines of code) (raw):
'use strict';
const { I18N_METHODS } = require('../i18n.js');
const isReferenceNode = (node) => {
if (node.type === 'TemplateLiteral') {
return false;
}
return node.type !== 'Literal' || typeof node.value !== 'string';
};
const extractI18nMethodAndArgs = (node) => {
let result = [];
if (node.type === 'CallExpression') {
const { callee } = node;
if (callee.type === 'MemberExpression') {
const { object, property } = callee;
if (object.name === 'i18n') {
result = [property.name, node.arguments];
}
}
}
return result;
};
module.exports = {
meta: {
docs: {
githubIssue: 'https://github.com/mozilla/eslint-plugin-amo/issues/232',
category: 'Possible Errors',
description:
'Ensure predictable static values are passed as i18n method arguments',
},
fixable: null,
schema: [],
messages: {
noDynamicValue:
'invalid argument type "{{ arg }}" passed to i18n.{{ method }}(). Only static values or calls to i18n methods are allowed.',
},
},
create(context) {
const SOURCE_CODE = context.sourceCode ?? context.getSourceCode();
return {
CallExpression(node) {
const [methodName, methodArgs] = extractI18nMethodAndArgs(node);
if (!methodName || !methodArgs || methodName.includes('ngettext')) {
return;
}
const positions = I18N_METHODS[methodName] || [];
positions.forEach((position) => {
const arg = methodArgs[position];
const [argMethod] = extractI18nMethodAndArgs(arg);
if (isReferenceNode(arg) && !argMethod) {
context.report({
node,
messageId: 'noDynamicValue',
data: {
method: methodName,
arg: SOURCE_CODE.getText(arg),
},
});
}
});
},
};
},
};