Appearance
Comment utiliser correctement le pipe i18nPlural
Résultat:
One item
Syntaxe Angular:
{{ 1 | i18nPlural:{'=0': 'No items', '=1': 'One item', 'other': '# items'} }}
L'internationalisation (i18n) est un aspect crucial du développement web moderne. Lorsque nous créons des applications destinées à un public international, nous devons adapter nos textes aux règles grammaticales de chaque langue, notamment pour les formes plurielles.
Imaginons que vous développiez une application de messagerie : afficher "1 messages" en français est incorrect, tout comme "0 message". Chaque nombre nécessite une forme adaptée, et ces règles varient selon les langues !
Comprendre le pipe i18nPlural
Le pipe i18nPlural
transforme un nombre en chaîne de caractères selon des règles de pluralisation. Il permet d'afficher le texte approprié en fonction d'une valeur numérique.
IMPORTANT
Le pipe i18nPlural
est conçu pour être utilisé dans les templates Angular, pas directement dans la classe du composant via injection.
Approches recommandées pour la pluralisation
1. Dans le template (recommandé)
La méthode la plus simple et la plus performante consiste à utiliser le pipe directement dans votre template :
html
{{ messages.length | i18nPlural: messageMapping }}
Avec le mapping défini dans le composant :
typescript
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-message-list',
standalone: true,
imports: [CommonModule],
template: `
<p>{{ messages.length | i18nPlural: messageMapping }}</p>
<button (click)="addMessage()">Ajouter un message</button>
`
})
export class MessageListComponent {
/**
* Collection de messages à afficher
*/
messages: string[] = [];
/**
* Mapping des formes plurielles pour l'affichage du nombre de messages
* - '=0': Cas spécifique pour zéro message
* - '=1': Cas spécifique pour un seul message
* - 'other': Cas par défaut pour tous les autres nombres
*/
messageMapping: {[k: string]: string} = {
'=0': 'Aucun message.',
'=1': 'Un message.',
'other': '# messages.'
};
/**
* Ajoute un nouveau message à la collection
*/
addMessage(): void {
this.messages.push(`Message ${this.messages.length + 1}`);
}
}
Cette approche profite du cache intégré du pipe et s'intègre parfaitement au cycle de détection des changements d'Angular.
2. Utiliser la syntaxe ICU directement
Angular supporte la syntaxe ICU (International Components for Unicode) qui permet une gestion plus riche des pluriels :
html
<p i18n>
{messages.length, plural,
=0 {Aucun message.}
=1 {Un message.}
other {{messages.length} messages.}
}
</p>
Cette approche est particulièrement recommandée si vous utilisez le système d'internationalisation intégré d'Angular, car elle permet l'extraction automatique des chaînes à traduire.
3. Utiliser NgLocalization pour la logique métier
Si vous avez besoin de déterminer la forme plurielle dans la classe du composant (par exemple pour une logique conditionnelle), utilisez le service NgLocalization
:
typescript
import { Component, inject } from '@angular/core';
import { CommonModule, NgLocalization } from '@angular/common';
@Component({
selector: 'app-message-status',
standalone: true,
imports: [CommonModule],
template: `<p>{{ statusText }}</p>`
})
export class MessageStatusComponent {
private loc = inject(NgLocalization);
messageCount = 5;
/**
* Calcule le texte d'état en fonction du nombre de messages
* en utilisant les règles de pluralisation de la locale active
*/
get statusText(): string {
const category = this.loc.getPluralCategory(this.messageCount);
const messageStatus: Record<string, string> = {
'zero': 'Boîte vide.',
'one': 'Vous avez un nouveau message.',
'other': `Vous avez ${this.messageCount} nouveaux messages.`
};
return messageStatus[category] || messageStatus.other;
}
}
Pourquoi éviter l'injection directe du pipe
Il existe plusieurs raisons importantes pour ne pas injecter le pipe directement dans la classe du composant :
ANTI-PATTERN
typescript
// ❌ À éviter
export class MessageComponent {
private i18nPluralPipe = inject(I18nPluralPipe);
getMessageText(count: number): string {
return this.i18nPluralPipe.transform(count, this.messageMapping);
}
}
- Vous perdez les optimisations de cache intégrées au pipe
- Cela complique les tests unitaires
- Cela mélange les responsabilités du composant
- Les performances peuvent être dégradées lors de la détection de changements
Fonctionnement des mappings
Le mapping pour i18nPlural
fonctionne avec ces règles :
- Les clés commençant par
=
correspondent à des valeurs exactes (=0
,=1
, etc.) - La clé
other
est utilisée pour toutes les autres valeurs - Le symbole
#
dans la valeur est remplacé par le nombre réel
Internationalisation avancée
Pour une véritable internationalisation, vous pouvez combiner l'approche ICU avec le système d'i18n d'Angular :
- Définissez vos messages avec la syntaxe ICU
- Utilisez l'outil d'extraction
ng extract-i18n
pour générer des fichiers XLIFF/XLF - Traduisez ces fichiers pour chaque langue cible
- Compilez votre application avec les différentes traductions
Depuis Angular 17, $localize
prend aussi en charge les ICUs à l'exécution, ce qui offre plus de flexibilité.
Exemple complet
Résumé des bonnes pratiques
Approche | Cas d'utilisation | Avantages |
---|---|---|
i18nPlural dans le template | Affichage simple | Performance optimale, facilité d'utilisation |
Syntaxe ICU | Internationalisation complète | Compatible avec l'extraction i18n d'Angular |
NgLocalization | Logique métier côté classe | Séparation des responsabilités |
CONSEIL
Gardez toujours vos chaînes de traduction dans un seul endroit (fichiers de traduction) plutôt que dispersées dans le code, pour faciliter la maintenance.