From d7518f0f099bc03ed2daab1565b5820132369822 Mon Sep 17 00:00:00 2001 From: alxndrsn Date: Fri, 7 Nov 2025 11:47:24 +0000 Subject: [PATCH] no-unused-keys: allow configuring of callExpression Closes #643 --- docs/rules/no-unused-keys.md | 4 +++- lib/rules/no-unused-keys.ts | 9 ++++++++- lib/utils/collect-keys.ts | 12 ++++++++---- tests/lib/rules/no-unused-keys.ts | 21 +++++++++++++++++++++ 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/docs/rules/no-unused-keys.md b/docs/rules/no-unused-keys.md index efc7d5df..258e852d 100644 --- a/docs/rules/no-unused-keys.md +++ b/docs/rules/no-unused-keys.md @@ -164,7 +164,8 @@ i18n.t('hi') "src": "./src", "extensions": [".js", ".vue"], "ignores": [], - "enableFix": false + "enableFix": false, + "callExpression": "^(\\$t|t|\\$tc|tc)$" } ] } @@ -174,6 +175,7 @@ i18n.t('hi') - `extensions`: an array to allow specified lintable target file extension. If you don't set any options, it set to `.js` and `.vue` as default. - `ignores`: An array of key names and patterns to exclude from the check. If you want to specify a pattern, specify a string such as `/pattern/`. - `enableFix`: if `true`, enable automatically remove unused keys on `eslint --fix`. If you don't set any options, it set to `false` as default. (This is an experimental feature.) +- `callExpression`: A regular expression used to identify translation function calls. ## :couple: Related Rules diff --git a/lib/rules/no-unused-keys.ts b/lib/rules/no-unused-keys.ts index a33ccded..879b5604 100644 --- a/lib/rules/no-unused-keys.ts +++ b/lib/rules/no-unused-keys.ts @@ -81,6 +81,9 @@ function create(context: RuleContext): RuleListener { const options = (context.options && context.options[0]) || {} const enableFix = options.enableFix const ignores = ((options.ignores || []) as string[]).map(toRegExp) + const callExpression = + (options.callExpression && new RegExp(options.callExpression)) || + /^(\$t|t|\$tc|tc)$/ function createVerifyContext( usedKeys: UsedKeys, @@ -512,7 +515,8 @@ function create(context: RuleContext): RuleListener { const localeMessages = getLocaleMessages(context) const usedLocaleMessageKeys = collectKeysFromAST( sourceCode.ast as VAST.ESLintProgram, - sourceCode.visitorKeys + sourceCode.visitorKeys, + callExpression ) const targetLocaleMessage = localeMessages.findBlockLocaleMessage( ctx.parserServices.customBlock @@ -601,6 +605,9 @@ export = createRule({ }, enableFix: { type: 'boolean' + }, + callExpression: { + type: 'string' } }, additionalProperties: false diff --git a/lib/utils/collect-keys.ts b/lib/utils/collect-keys.ts index 8f5346b2..5102d055 100644 --- a/lib/utils/collect-keys.ts +++ b/lib/utils/collect-keys.ts @@ -20,7 +20,10 @@ const debug = debugBuilder('eslint-plugin-vue-i18n:collect-keys') * * @param {CallExpression} node */ -function getKeyFromCallExpression(node: VAST.ESLintCallExpression) { +function getKeyFromCallExpression( + node: VAST.ESLintCallExpression, + callExpression?: RegExp +) { const funcName = (node.callee.type === 'MemberExpression' && node.callee.property.type === 'Identifier' && @@ -29,7 +32,7 @@ function getKeyFromCallExpression(node: VAST.ESLintCallExpression) { '' if ( - !/^(\$t|t|\$tc|tc)$/.test(funcName) || + !(callExpression ?? /^(\$t|t|\$tc|tc)$/).test(funcName) || !node.arguments || !node.arguments.length ) { @@ -121,7 +124,8 @@ function collectKeyResourcesFromFiles(fileNames: string[], cwd: string) { */ export function collectKeysFromAST( node: VAST.ESLintProgram, - visitorKeys?: VisitorKeys + visitorKeys?: VisitorKeys, + callExpression?: RegExp ): string[] { debug('collectKeysFromAST') @@ -168,7 +172,7 @@ export function collectKeysFromAST( } } else if (node.type === 'CallExpression') { debug('CallExpression handling ...') - const key = getKeyFromCallExpression(node) + const key = getKeyFromCallExpression(node, callExpression) if (key) { results.add(String(key)) } diff --git a/tests/lib/rules/no-unused-keys.ts b/tests/lib/rules/no-unused-keys.ts index 5e3c0a1a..53aa32d7 100644 --- a/tests/lib/rules/no-unused-keys.ts +++ b/tests/lib/rules/no-unused-keys.ts @@ -289,6 +289,27 @@ new RuleTester({ } } ` + }, + { + filename: 'test.vue', + code: ` + + { + "foo": "foo", + "bar": { + "nest": "nest", + }, + } + + `, + options: [{ callExpression: 'customFn\\d' }] } ], invalid: [