Skip to content

Commit

Permalink
feat(eslint-plugin-template): [i18n] add requireDescription option (#988
Browse files Browse the repository at this point in the history
)
  • Loading branch information
smithpb committed Jun 10, 2022
1 parent d2868ea commit 8f55ba8
Show file tree
Hide file tree
Showing 3 changed files with 274 additions and 8 deletions.
195 changes: 195 additions & 0 deletions packages/eslint-plugin-template/docs/rules/i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,102 @@ interface Options {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```

<br>

---

<br>

#### Custom Config

```json
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkId": false,
"requireDescription": true
}
]
}
}
```

<br>

#### ❌ Invalid Code

```html
<span i18n="A balloon that displays data" data-balloon="Translated title" i18n-data-balloon>
~~~~~~~~~~~~
Hello
</span>
```

<br>

---

<br>

#### Custom Config

```json
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"requireDescription": true
}
]
}
}
```

<br>

#### ❌ Invalid Code

```html
<h1 i18n="Title of the sample@@custom-id" i18n-title="@@title-id" title="Translated title">
~~~~~
Hello
</h1>
```

<br>

---

<br>

#### Custom Config

```json
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"requireDescription": true,
"checkId": false
}
]
}
}
```

<br>

#### ❌ Invalid Code

```html
<img [src]="logo" i18n-title title="App Logo" i18n-alt="App logo" alt="App Logo"/>
~~~~~
```

</details>

<br>
Expand Down Expand Up @@ -1262,6 +1358,105 @@ interface Options {

#### Custom Config

```json
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkId": false,
"requireDescription": true
}
]
}
}
```

<br>

#### ✅ Valid Code

```html
<h1 i18n="An introduction header for this sample" i18n-title="Title of the sample" title="Translated title">
Hello i18n!
</h1>
```

<br>

---

<br>

#### Custom Config

```json
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"requireDescription": true
}
]
}
}
```

<br>

#### ✅ Valid Code

```html
<h1 i18n="An introduction header for this sample@@custom-id" i18n-title="Title of the sample@@title-id" title="Translated title">
Hello i18n!
</h1>
```

<br>

---

<br>

#### Custom Config

```json
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkId": false,
"requireDescription": true
}
]
}
}
```

<br>

#### ✅ Valid Code

```html
<img
[src]="logo"
i18n-title="Logo for the app"
title="App Logo"
i18n-alt="Translated alt logo"
alt="Alternate logo"
/>
```

<br>

---

<br>

#### Custom Config

```json
{
"rules": {
Expand Down
26 changes: 18 additions & 8 deletions packages/eslint-plugin-template/src/rules/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,18 +250,28 @@ export default createESLintRule<Options, MessageIds>({
keySpan ?? sourceSpan,
);

if (checkId && i18n) {
const { customId } = i18n;
if (i18n) {
const { customId, description } = i18n;

if (isEmpty(customId)) {
if (checkId) {
if (isEmpty(customId)) {
context.report({
messageId: 'i18nCustomIdOnAttribute',
loc: keyOrSourceSpanLoc,
data: { attributeName },
});
} else {
const sourceSpans = collectedCustomIds.get(customId) ?? [];
collectedCustomIds.set(customId, [...sourceSpans, sourceSpan]);
}
}

if (requireDescription && isEmpty(description)) {
context.report({
messageId: 'i18nCustomIdOnAttribute',
messageId: 'i18nMissingDescription',
loc: keyOrSourceSpanLoc,
data: { attributeName },
});
} else {
const sourceSpans = collectedCustomIds.get(customId) ?? [];
collectedCustomIds.set(customId, [...sourceSpans, sourceSpan]);
}
}

Expand Down Expand Up @@ -340,7 +350,7 @@ export default createESLintRule<Options, MessageIds>({
handleElement(node);
},
}),
...((checkAttributes || checkId) && {
...((checkAttributes || checkId || requireDescription) && {
[`Element$1 > TextAttribute[value=${PL_PATTERN}]`](
node: StronglyTypedTextAttribute,
) {
Expand Down
61 changes: 61 additions & 0 deletions packages/eslint-plugin-template/tests/rules/i18n/cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,34 @@ export const valid = [
`,
options: [{ requireDescription: true }],
},
{
code: `
<h1 i18n="An introduction header for this sample" i18n-title="Title of the sample" title="Translated title">
Hello i18n!
</h1>
`,
options: [{ checkId: false, requireDescription: true }],
},
{
code: `
<h1 i18n="An introduction header for this sample@@custom-id" i18n-title="Title of the sample@@title-id" title="Translated title">
Hello i18n!
</h1>
`,
options: [{ requireDescription: true }],
},
{
code: `
<img
[src]="logo"
i18n-title="Logo for the app"
title="App Logo"
i18n-alt="Translated alt logo"
alt="Alternate logo"
/>
`,
options: [{ checkId: false, requireDescription: true }],
},
{
code: `
<span i18n="@@custom-id">Some text to translate</span>
Expand Down Expand Up @@ -490,4 +518,37 @@ export const invalid = [
messageId: i18nMissingDescription,
options: [{ requireDescription: true }],
}),
convertAnnotatedSourceToFailureCase({
description: 'should fail if i18n-<attr> description is missing',
annotatedSource: `
<span i18n="A balloon that displays data" data-balloon="Translated title" i18n-data-balloon>
~~~~~~~~~~~~
Hello
</span>
`,
messageId: i18nMissingDescription,
options: [{ checkId: false, requireDescription: true }],
}),
convertAnnotatedSourceToFailureCase({
description:
'should fail if i18n-<attr> description is missing, despite an ID being provided',
annotatedSource: `
<h1 i18n="Title of the sample@@custom-id" i18n-title="@@title-id" title="Translated title">
~~~~~
Hello
</h1>
`,
messageId: i18nMissingDescription,
options: [{ requireDescription: true }],
}),
convertAnnotatedSourceToFailureCase({
description:
'should fail if i18n-<attr> description is missing when there is no text content to translate',
annotatedSource: `
<img [src]="logo" i18n-title title="App Logo" i18n-alt="App logo" alt="App Logo"/>
~~~~~
`,
messageId: i18nMissingDescription,
options: [{ requireDescription: true, checkId: false }],
}),
];

0 comments on commit 8f55ba8

Please sign in to comment.