Skip to content

Commit 61b0c94

Browse files
authoredMay 10, 2024··
feat: add no-deprecated-tc rule (#510)
* feat: add `no-deprecated-tc` rule * Create new-apples-ring.md
1 parent 4a966e1 commit 61b0c94

File tree

6 files changed

+170
-0
lines changed

6 files changed

+170
-0
lines changed
 

‎.changeset/new-apples-ring.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@intlify/eslint-plugin-vue-i18n": patch
3+
---
4+
5+
feat: add `no-deprecated-tc` rule

‎docs/rules/index.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
| Rule ID | Description | |
2626
|:--------|:------------|:---|
2727
| [@intlify/vue-i18n/<wbr>key-format-style](./key-format-style.html) | enforce specific casing for localization keys | |
28+
| [@intlify/vue-i18n/<wbr>no-deprecated-tc](./no-deprecated-tc.html) | disallow using deprecated `tc` or `$tc` (Deprecated in Vue I18n 10.0.0, removed fully in Vue I18n 11.0.0) | |
2829
| [@intlify/vue-i18n/<wbr>no-duplicate-keys-in-locale](./no-duplicate-keys-in-locale.html) | disallow duplicate localization keys within the same locale | |
2930
| [@intlify/vue-i18n/<wbr>no-dynamic-keys](./no-dynamic-keys.html) | disallow localization dynamic keys at localization methods | |
3031
| [@intlify/vue-i18n/<wbr>no-missing-keys-in-other-locales](./no-missing-keys-in-other-locales.html) | disallow missing locale message keys in other locales | |

‎docs/rules/no-deprecated-tc.md

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
title: '@intlify/vue-i18n/no-deprecated-tc'
3+
description: disallow using deprecated `tc` or `$tc` (Deprecated in Vue I18n 10.0.0, removed fully in Vue I18n 11.0.0)
4+
since: v3.0.0
5+
---
6+
7+
# @intlify/vue-i18n/no-deprecated-tc
8+
9+
> disallow using deprecated `tc` or `$tc` (Deprecated in Vue I18n 10.0.0, removed fully in Vue I18n 11.0.0)
10+
11+
If you are migrating from Vue I18n v9 to v10, `tc` or `$tc` should be replaced with `t` or `$t`.
12+
13+
## :book: Rule Details
14+
15+
This rule reports use of deprecated `tc` or `$tc` (Deprecated in Vue I18n 10.0.0, removed fully in Vue I18n 11.0.0)
16+
17+
:-1: Examples of **incorrect** code for this rule:
18+
19+
<eslint-code-block>
20+
21+
<!-- eslint-skip -->
22+
23+
```vue
24+
<script>
25+
/* eslint @intlify/vue-i18n/no-deprecated-tc: 'error' */
26+
</script>
27+
<template>
28+
<!-- ✗ BAD -->
29+
<p>{{ $tc('banana') }}</p>
30+
</template>
31+
```
32+
33+
</eslint-code-block>
34+
35+
:+1: Examples of **correct** code for this rule:
36+
37+
<eslint-code-block>
38+
39+
<!-- eslint-skip -->
40+
41+
```vue
42+
<script>
43+
/* eslint @intlify/vue-i18n/no-deprecated-tc: 'error' */
44+
</script>
45+
<template>
46+
<!-- ✓ GOOD -->
47+
<p>{{ $t('banana', 1) }}</p>
48+
</template>
49+
```
50+
51+
</eslint-code-block>
52+
53+
## :books: Further reading
54+
55+
- [Vue I18n > Breaking Changes in v10 - Deprecate tc and $tc for Legacy API mode](https://vue-i18n.intlify.dev/guide/migration/breaking10.html#deprecate-tc-and-tc-for-legacy-api-mode)
56+
57+
## :rocket: Version
58+
59+
This rule was introduced in `@intlify/eslint-plugin-vue-i18n` v3.0.0
60+
61+
## :mag: Implementation
62+
63+
- [Rule source](https://github.com/intlify/eslint-plugin-vue-i18n/blob/master/lib/rules/no-deprecated-tc.ts)
64+
- [Test source](https://github.com/intlify/eslint-plugin-vue-i18n/tree/master/tests/lib/rules/no-deprecated-tc.ts)

‎lib/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import noDeprecatedI18nComponent from './rules/no-deprecated-i18n-component'
1111
import noDeprecatedI18nPlaceAttr from './rules/no-deprecated-i18n-place-attr'
1212
import noDeprecatedI18nPlacesProp from './rules/no-deprecated-i18n-places-prop'
1313
import noDeprecatedModuloSyntax from './rules/no-deprecated-modulo-syntax'
14+
import noDeprecatedTc from './rules/no-deprecated-tc'
1415
import noDuplicateKeysInLocale from './rules/no-duplicate-keys-in-locale'
1516
import noDynamicKeys from './rules/no-dynamic-keys'
1617
import noHtmlMessages from './rules/no-html-messages'
@@ -43,6 +44,7 @@ export = {
4344
'no-deprecated-i18n-place-attr': noDeprecatedI18nPlaceAttr,
4445
'no-deprecated-i18n-places-prop': noDeprecatedI18nPlacesProp,
4546
'no-deprecated-modulo-syntax': noDeprecatedModuloSyntax,
47+
'no-deprecated-tc': noDeprecatedTc,
4648
'no-duplicate-keys-in-locale': noDuplicateKeysInLocale,
4749
'no-dynamic-keys': noDynamicKeys,
4850
'no-html-messages': noHtmlMessages,

‎lib/rules/no-deprecated-tc.ts

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* @author kazuya kawaguchi (a.k.a. kazupon)
3+
*/
4+
import { defineTemplateBodyVisitor } from '../utils/index'
5+
import { createRule } from '../utils/rule'
6+
7+
import type { RuleContext, RuleListener } from '../types'
8+
import type { AST as VAST } from 'vue-eslint-parser'
9+
10+
function checkCallExpression(
11+
context: RuleContext,
12+
node: VAST.ESLintCallExpression
13+
) {
14+
const funcName =
15+
(node.callee.type === 'MemberExpression' &&
16+
node.callee.property.type === 'Identifier' &&
17+
node.callee.property.name) ||
18+
(node.callee.type === 'Identifier' && node.callee.name) ||
19+
''
20+
21+
if (/^(\$tc|tc)$/.test(funcName)) {
22+
context.report({
23+
node,
24+
message: `'${funcName}' is used, but it is deprecated. Use 't' or '$t' instead.`
25+
})
26+
return
27+
}
28+
}
29+
30+
function create(context: RuleContext): RuleListener {
31+
return defineTemplateBodyVisitor(
32+
context,
33+
{
34+
CallExpression(node: VAST.ESLintCallExpression) {
35+
checkCallExpression(context, node)
36+
}
37+
},
38+
{
39+
CallExpression(node: VAST.ESLintCallExpression) {
40+
checkCallExpression(context, node)
41+
}
42+
}
43+
)
44+
}
45+
46+
export = createRule({
47+
meta: {
48+
type: 'suggestion',
49+
docs: {
50+
description:
51+
'disallow using deprecated `tc` or `$tc` (Deprecated in Vue I18n 10.0.0, removed fully in Vue I18n 11.0.0)',
52+
category: 'Best Practices',
53+
url: 'https://eslint-plugin-vue-i18n.intlify.dev/rules/no-deprecated-tc.html',
54+
recommended: false
55+
},
56+
fixable: null,
57+
schema: []
58+
},
59+
create
60+
})

‎tests/lib/rules/no-deprecated-tc.ts

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* @author kazuya kawaguchi (a.k.a. kazupon)
3+
*/
4+
import { RuleTester } from '../eslint-compat'
5+
import rule from '../../../lib/rules/no-deprecated-tc'
6+
import * as vueParser from 'vue-eslint-parser'
7+
8+
const tester = new RuleTester({
9+
languageOptions: { parser: vueParser, ecmaVersion: 2015 }
10+
})
11+
12+
tester.run('no-deprecated-tc', rule as never, {
13+
valid: [],
14+
invalid: [
15+
{
16+
// tc key
17+
code: `tc('banana')`,
18+
errors: [`'tc' is used, but it is deprecated. Use 't' or '$t' instead.`]
19+
},
20+
{
21+
// $tc key
22+
code: `$tc('banana')`,
23+
errors: [`'$tc' is used, but it is deprecated. Use 't' or '$t' instead.`]
24+
},
25+
{
26+
// via i18n instance
27+
code: `i18n.tc('banana')`,
28+
errors: [`'tc' is used, but it is deprecated. Use 't' or '$t' instead.`]
29+
},
30+
{
31+
// using mustaches in template block
32+
code: `<template>
33+
<p>{{ $tc('banana') }}</p>
34+
</template>`,
35+
errors: [`'$tc' is used, but it is deprecated. Use 't' or '$t' instead.`]
36+
}
37+
]
38+
})

0 commit comments

Comments
 (0)
Please sign in to comment.