Replay

Apprendre Angular en 1h

Je me donne un objectif: vous faire découvrir et apprendre Angular en 1 heure: composant, syntaxe dans les templates, les directives, les signaux, les routeurs, les services, l'injection de dépendances, les observables et les requêtes HTTP. Le nécessaire pour faire une application Angular !.

Skip to content

Vous souhaitez recevoir de l'aide sur ce sujet ? rejoignez la communauté Angular.fr sur Discord.

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);
  }
}
  1. Vous perdez les optimisations de cache intégrées au pipe
  2. Cela complique les tests unitaires
  3. Cela mélange les responsabilités du composant
  4. 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 :

  1. Définissez vos messages avec la syntaxe ICU
  2. Utilisez l'outil d'extraction ng extract-i18n pour générer des fichiers XLIFF/XLF
  3. Traduisez ces fichiers pour chaque langue cible
  4. 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

ApprocheCas d'utilisationAvantages
i18nPlural dans le templateAffichage simplePerformance optimale, facilité d'utilisation
Syntaxe ICUInternationalisation complèteCompatible avec l'extraction i18n d'Angular
NgLocalizationLogique métier côté classeSé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.