Ensures following best practices for i18n. Checks for missing i18n attributes on elements and attributes containing texts. Can also check for texts without i18n attribute, elements that do not use custom ID (@@) feature and duplicate custom IDs
-
Type: suggestion
-
🔧 Supports autofix (
--fix
) -
💡 Provides suggestions on how to fix issues (https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions)
The rule accepts an options object with the following properties:
interface Options {
boundTextAllowedPattern?: string;
/**
* Default: `true`
*/
checkAttributes?: boolean;
/**
* Default: `true`
*/
checkDuplicateId?: boolean;
/**
* Default: `true`
*/
checkId?: boolean;
/**
* Default: `true`
*/
checkText?: boolean;
/**
* Default: `["autocomplete","charset","class","color","colspan","dir","fill","for","formArrayName","formControlName","formGroupName","height","href","id","lang","list","name","ngClass","ngProjectAs","role","routerLink","routerLinkActive","src","stroke","stroke-width","style","svgIcon","tabindex","target","type","value","viewBox","width","xmlns"]`
*/
ignoreAttributes?: string[];
ignoreTags?: string[];
requireDescription?: boolean;
}
The following examples are generated automatically from the actual unit tests within the plugin, so you can be assured that their behavior is accurate based on the current commit.
❌ - Toggle examples of incorrect code for this rule
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<div tooltip="This requires translation"></div>
~~~~~~~
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"ignoreTags": []
}
]
}
}
<div>
<span>test{{data_from_backend}}</span>
~~~~~~~~~~~~~~~~~~~~~~~~~
</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkAttributes": false
}
]
}
}
{ value, plural, =0 {<div>No elements</div>} =1 {111} }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkId": false
}
]
}
}
<div>
<ng-container>Some text t@ tr1nslate</ng-container>
~~~~~~~~~~~~~~~~~~~~~~~~~~~
</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<p>Lorem ipsum <em i18n="@@dolor">dolor</em> sit amet.</p>
~~~~~~~~~~~~ ~~~~~~~~~
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<div tooltip="This requires translation" i18n-tooltip></div>
~~~~~~~
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"ignoreAttributes": [
"span[label]"
]
}
]
}
}
<div>
<span i18n label="label is ignored in 'ignoreAttributes'">
~
Missing custom ID
</span>
~
</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<div
i18n-tooltip="@@custom-id"
tooltip="This requires translation"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
label="Custom label"
~~~~~~~~~~~~~~~~~~~~
i18n-label="@@custom-id"
></div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"ignoreTags": []
}
]
}
}
<h3 i18n="@@myId">Hello</h3>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<p i18n="@@myId">Good bye</p>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<div i18n-tooltip="@@custom-id" tooltip="This requires translation">
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<span i18n="@@custom-id">Some text to translate</span>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<div i18n-tooltip="@@custom-id" tooltip="This requires translation">
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<span i18n="@@custom-id">Some text to translate</span>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
</div>
<div i18n-label="@@custom-id" label="A label"></div>
~~~~~~~~~~~~~~~
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"ignoreAttributes": [
"span[label]"
]
}
]
}
}
<div
tooltip="This requires translation"
~~~~~~~
i18n-placeholder
placeholder="More translation, please"
~~~~~~~~~~~
class="red"
>
<div
*ngIf="true"
width="100px"
label="Templates need translation too."
~~~~~
>
<span i18n label="label is ignored in 'ignoreAttributes'">
~
Missing custom ID
</span>
~
</div>
</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkId": false,
"requireDescription": true
}
]
}
}
<h1 i18n>Hello</h1>
~~~~~~~~~~~~~~~~~~~
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"requireDescription": true
}
]
}
}
<h1 i18n="@@custom-id">Hello</h1>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkId": false,
"requireDescription": true
}
]
}
}
<span i18n="A balloon that displays data" data-balloon="Translated title" i18n-data-balloon>
~~~~~~~~~~~~
Hello
</span>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"requireDescription": true
}
]
}
}
<h1 i18n="Title of the sample@@custom-id" i18n-title="@@title-id" title="Translated title">
~~~~~
Hello
</h1>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"requireDescription": true,
"checkId": false
}
]
}
}
<img [src]="logo" i18n-title title="App Logo" i18n-alt="App logo" alt="App Logo"/>
~~~~~
✅ - Toggle examples of correct code for this rule
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<div>
<span i18n="@@custom-id">Some text to translate</span>
</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<div>
<span class="red" i18n="@@custom-id">
Some text to translate
</span>
</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkId": false,
"ignoreAttributes": [
"tooltip"
]
}
]
}
}
<div tooltip="This tooltip property is ignored">
<span i18n>Some text to translate</span>
</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkText": false
}
]
}
}
<div i18n-tooltip="@@tooltip.label" tooltip="This tooltip property is ignored">
<span>Some text to translate</span>
</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"ignoreTags": [
"mat-icon"
]
}
]
}
}
<div i18n-tooltip="@@tooltip.label" tooltip="This tooltip property is ignored">
<mat-icon>valid</mat-icon>
</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<div>-{{data_from_backend}}</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<div>1{{data_from_backend}}</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<div>-1{{data_from_backend}}</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"boundTextAllowedPattern": "My company untranslatable name"
}
]
}
}
<div>
My company untranslatable name{{data_from_backend}}
</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"ignoreTags": [
"my-component"
]
}
]
}
}
<my-component size="s"></my-component>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkAttributes": false,
"checkId": true,
"checkText": false
}
]
}
}
<p i18n="@@customId">Lorem ipsum <em>dolor</em> sit amet.</p>
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<a
mat-button
ngClass="class"
routerLink="exclusions"
i18n="@@keywording.tools.exclusions"
>
Exclusions
</a>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkId": true,
"checkText": true
}
]
}
}
<a
mat-button
routerLink="exclusions"
i18n="@@keywording.tools.exclusions"
>
Exclusions
</a>
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<ng-template #errorMessage>
{{ error.title }}
</ng-template>
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<ng-container i18n="@@description">
{ value, plural, =0 {<div>No elements</div>} =1 {111} }
</ng-container>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkId": false
}
]
}
}
<span i18n>
The author is {gender, select, male {male} female {female} other {other}}
</span>
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<mat-option *ngFor="let mode of modes" [value]="mode.id" i18n="@@option">
{mode.name, select, mode {mode} other { {{mode.name}} } }
</mat-option>
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<ng-container ngProjectAs="top">&ngsp;</ng-container>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkText": false
}
]
}
}
<p [ngPlural]="components">
<ng-template ngPluralCase="1">1 component removed</ng-template>
<ng-template ngPluralCase="1">{{components}} components removed</ng-template>
</p>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkAttributes": false,
"checkId": false,
"checkText": false
}
]
}
}
<div tooltip="This requires translation"></div>
<div>
<span i18n label="valid with i18n">Some text to translate</span>
</div>
<div tooltip="This requires translation" i18n-tooltip></div>
<div>
<ng-container>Some text t@ tr1nslate</ng-container>
</div>
<div>
<span>-{{data_from_backend}}</span>
</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<div label="1">
<div matBadge="⁠">5</div>
</div>
{
"rules": {
"@angular-eslint/template/i18n": [
"error"
]
}
}
<div ariaselected="0"></div>
<div>+</div>
<span> </span>
<span>123</span>
<ng-content select=".content-area"></ng-content>
<ul i18n="@@list">
<li>ItemA</li>
<li>ItemB</li>
<li>ItemC</li>
</ul>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkId": false,
"requireDescription": true
}
]
}
}
<h1 i18n="An introduction header for this sample">Hello i18n!</h1>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"requireDescription": true
}
]
}
}
<h1 i18n="An introduction header for this sample@@custom-id">Hello i18n!</h1>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkId": false,
"requireDescription": true
}
]
}
}
<h1 i18n="An introduction header for this sample" i18n-title="Title of the sample" title="Translated title">
Hello i18n!
</h1>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"requireDescription": true
}
]
}
}
<h1 i18n="An introduction header for this sample@@custom-id" i18n-title="Title of the sample@@title-id" title="Translated title">
Hello i18n!
</h1>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkId": false,
"requireDescription": true
}
]
}
}
<img
[src]="logo"
i18n-title="Logo for the app"
title="App Logo"
i18n-alt="Translated alt logo"
alt="Alternate logo"
/>
{
"rules": {
"@angular-eslint/template/i18n": [
"error",
{
"checkDuplicateId": false
}
]
}
}
<span i18n="@@custom-id">Some text to translate</span>
<span i18n="@@custom-id">Some text to translate</span>