Skip to content

Commit 252d125

Browse files
authored
Fix false positives of key used in <i18n> component in no-unused-keys rule. (#92)
* Fix false positives of key used in `<i18n>` component in `no-unused-keys` rule. * Add supports `<i18n-t>` component
1 parent 8c912c1 commit 252d125

File tree

6 files changed

+73
-8
lines changed

6 files changed

+73
-8
lines changed

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
],
66
"eslint.alwaysShowStatus": true,
77
"eslint.packageManager": "yarn",
8-
"eslint.run": "onSave"
8+
"eslint.run": "onSave",
9+
"npm.packageManager": "yarn"
910
}

lib/utils/collect-keys.js

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const debug = require('debug')('eslint-plugin-vue-i18n:collect-keys')
1818
* @typedef {import('vue-eslint-parser').AST.Node} Node
1919
* @typedef {import('vue-eslint-parser').AST.ESLintCallExpression} CallExpression
2020
* @typedef {import('vue-eslint-parser').AST.VDirective} VDirective
21+
* @typedef {import('vue-eslint-parser').AST.VAttribute} VAttribute
2122
*/
2223

2324
/**
@@ -51,6 +52,17 @@ function getKeyFromVDirective (node) {
5152
}
5253
}
5354

55+
/**
56+
* @param {VAttribute} node
57+
*/
58+
function getKeyFromI18nComponent (node) {
59+
if (node.value && node.value.type === 'VLiteral') {
60+
return node.value.value
61+
} else {
62+
return null
63+
}
64+
}
65+
5466
function getParser (parser) {
5567
if (parser) {
5668
try {
@@ -132,11 +144,28 @@ function collectKeysFromAST (node, visitorKeys) {
132144
*/
133145
function enterNode (node) {
134146
if (node.type === 'VAttribute') {
135-
if (node.directive && (node.key.name.name === 't' || node.key.name === 't' /* parser v5 */)) {
136-
debug("call VAttribute[directive=true][key.name.name='t'] handling ...")
137-
const key = getKeyFromVDirective(node)
138-
if (key) {
139-
results.add(key)
147+
if (node.directive) {
148+
if (node.key.name.name === 't' || node.key.name === 't' /* parser v5 */) {
149+
debug("call VAttribute[directive=true][key.name.name='t'] handling ...")
150+
const key = getKeyFromVDirective(node)
151+
if (key) {
152+
results.add(key)
153+
}
154+
}
155+
} else {
156+
if (
157+
node.key.name === 'path' &&
158+
(
159+
node.parent.parent.name === 'i18n' ||
160+
node.parent.parent.name === 'i18n-t'
161+
)
162+
) {
163+
debug("call VElement:matches([name=i18n], [name=i18n-t]) > VStartTag > VAttribute[key.name='path'] handling ...")
164+
165+
const key = getKeyFromI18nComponent(node)
166+
if (key) {
167+
results.add(key)
168+
}
140169
}
141170
}
142171
} else if (node.type === 'CallExpression') {

tests/fixtures/no-unused-keys/valid/vue-cli-format/locales/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
"link": "@:messages.hello"
66
},
77
"hello_dio": "hello underscore DIO!",
8-
"hello {name}": "hello {name}!"
8+
"hello {name}": "hello {name}!",
9+
"term": "I accept xxx {0}."
910
}

tests/fixtures/no-unused-keys/valid/vue-cli-format/locales/ja.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
"link": "@:messages.hello"
66
},
77
"hello_dio": "こんにちは、アンダースコア DIO!",
8-
"hello {name}": "こんにちは、{name}!"
8+
"hello {name}": "こんにちは、{name}!",
9+
"term": "私は xxx の{0}に同意します。"
910
}

tests/fixtures/no-unused-keys/valid/vue-cli-format/src/App.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<template>
22
<div id="app">
33
<p v-t="'hello_dio'">{{ $t('messages.link') }}</p>
4+
<i18n path="term" tag="label" for="tos">
5+
<a :href="url" target="_blank">{{ $t('tos') }}</a>
6+
</i18n>
47
</div>
58
</template>
69

tests/lib/rules/no-unused-keys.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,36 @@ new RuleTester({
5656
}
5757
}
5858
</script>`
59+
}, {
60+
// <i18n> component
61+
filename: 'test.vue',
62+
code: `
63+
<template>
64+
<i18n path="message_key" tag="p" />
65+
</template>
66+
<i18n>
67+
{
68+
"en": {
69+
"message_key": "hi"
70+
}
71+
}
72+
</i18n>
73+
`
74+
}, {
75+
// <i18n-t> component
76+
filename: 'test.vue',
77+
code: `
78+
<template>
79+
<i18n-t path="message_key" tag="p" />
80+
</template>
81+
<i18n>
82+
{
83+
"en": {
84+
"message_key": "hi"
85+
}
86+
}
87+
</i18n>
88+
`
5989
}],
6090
invalid: [{
6191
// sfc supports

0 commit comments

Comments
 (0)