'Grammatically correct plural / singular endings

Using a for loop, I have created a counter for late items by looping through items retrieved in a web request, setting a property of late as true if conditions are met, and incrementing the counter.

Using *ngIf, I could do the following:

<h5 *ngIf="lateCount != 1">You have {{lateCount}} late items.</h5>
<h5 *ngIf="lateCount == 1">You have {{lateCount}} late item.</h5>

Is there a way to do this without two *ngIfs?



Solution 1:[1]

Well you can trigger only s symbol on condition:

<h5>You have {{lateCount}} late item<ng-container *ngIf="lateCount == 1">s</ng-container>.</h5>

Another approach would be to write a pipe that does this for you, or furthermore, you can use Angular i18n (any other library) that provides the functionality to work with pluralization.

Solution 2:[2]

I know this question was asked a lot of time ago, but just to complete the argument there's another way you can accomplish the given task and that's by using the ngPlural directive.

Primarily ngPlural directive adds/removes DOM elements based on a numeric values

The ngPlural directive is very handy and can be used with the Common Locale Data Repository (CLDR) defined category matches such as: one, few or many. As from the angular documentation you can use the directive as follows:

<some-element [ngPlural]="value">
    <ng-template ngPluralCase="=0">there is nothing</ng-template>
    <ng-template ngPluralCase="=1">there is one</ng-template>
    <ng-template ngPluralCase="few">there are a few</ng-template>
</some-element>

For more information about the directive please see ngPlural. Hope it helps :)

Solution 3:[3]

I know it's a bit late, but there's a neater way to solve the problem, with pipes.

Here you can learn how to use it, it's really simple and reusable:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
      name: 'pluralSingular'
})
export class PluralSingularPipe implements PipeTransform {
        transform(number: number, singularText: string, pluralText: string = null): string {
      let pluralWord = pluralText ? pluralText : `${singularText}s`;
                return number > 1 ? `${number} ${pluralWord}` : `${number} ${singularText}`;
     }
}

Usage:

{{ someNumberVariable | pluralSingular:'city':'cities }}

Solution 4:[4]

As the answer below says you can use NgPlural

Your template should look like:

<h5 [ngPlural]="lateCount">
  You have {{lateCount}} late
  <ng-template ngPluralCase="=1">item.</ng-template>
  <ng-template ngPluralCase="other">items.</ng-template>
</h5>

Solution 5:[5]

I don't think we should be doing if/else logic on English plural words.
Let's make a smart suffix pipe instead.

  1. This pipe runs logic on plural words, defaulting to s.
  2. Optionally add a replacement plural suffix like ies. Then words ending in y are replaced with ies.

Stackblitz

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'plural',
})
export class PluralPipe implements PipeTransform {
  transform(word: string, count: number, pluralForm: string = 's'): string {
    let transformed;
    // 'ies' vs singular 'y' (city / cities)
    if (pluralForm === 'ies') {
      // replace y with ies
      transformed = count != 1 ? word.replace(/.$/, pluralForm) : word;
    } else {
      // default to plural 's' (applicant / applicants)
      transformed = count === 1 ? word : word + pluralForm;
    }

    // console.log(count, word, transformed);
    return transformed;
  }
}

Basic usage (s is default)

{{ 'comment' | plural: 2 }} // comments

Advanced usage (ies for plural replaces words ending in y)

{{ 'reply' | plural: 3:'ies' }} // replies

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Swinkaran
Solution 3
Solution 4 Alex Z
Solution 5