Search

Laravel 5: String Pluralization Syntax

February 19, 2018 —John Koster

In the previous sections, we briefly explored the concept of pluralization in regards to translation lines. In this section, we will explore the pluralization syntax in greater detail and develop our pluralization skills a little more.

#Handling Specific Numbers

Sometimes it is useful to associate a given message number with exactly one number. In previous examples, we've seen how to handle the pluralization case where the number of items is exactly 0, however, we can expand this idea to any arbitrary number we like.

Provided the following language file is available at resources/lang/en/plural.php:

1<?php
2 
3return [
4 
5 'messages' =>
6 
7 '{0}You\'re all caught up!
8 |{1}You have one unread message.
9 |{41}You have an oddly specific number of messages!
10 |You have :count unread messages',
11 
12];

We can now handle specific numbers with relative ease:

1<?php
2// Ask the Service Container for a translator instance.
3$translator = app('translator');
4 
5// Translate a message with 1 item.
6$oneItem = $translator->transChoice('plural.messages', 1);
7 
8// Translate a message with 41 item.
9$specificNumber = $translator->transChoice(
10 'plural.messages', 41
11 );

After the above code has executed, we would have the following values stored in our local variables:

Variable Name Value
$oneItem You have one unread message.
$specificNumber You have an oddly specific number of messages!

#Examples of Specific Numbers

The following table will show more examples of handling specific numbers when dealing with pluralization translation. The table will use the following translation message definition:

1{0} There are no books!
2|{1,2,3} You have one, two or three books.
3|{4}Four is a great number of books!
4|The number of books you have is uncountable!
Count Result
0 There are no books!
1 You have one, two or three books.
2 You have one, two or three books.
3 You have one, two or three books.
4 Four is a great number of books!
5 You have one, two or three books.

It would seem that passing a $number of 5 would result in the message The number of books you have is uncountable! to be returned. Instead, we get the same message as if we had passed in a count of 1, 2, or 3.

In previous versions of Laravel, which relied on the Symfony translation components, we could get around this issue by prefixing the entire translation line with a single pipe (|) character. However, doing this in Laravel 5.5 would result in the message There are no books! being returned; we have to very explicit about our rule-set, and this brings us into the topic of ranges.

We can define a range of numbers to include for the translation line by enclosing the rule within square brackets ([ and ]). The lower bounds of the range is listed first, and the upper-bounds of the range is listed second, with the range boundaries separated by a comma (,):

1{0} There are no books!
2|{1,2,3} You have one, two or three books.
3|{4} Four is a great number of books!
4|[5,*]The number of books you have is uncountable!

Now, the following function call will return the expected result of The number of books you have is uncountable!.

Syntax and Backwards Compatibility

Notice that there are no spaces between the lower and upper bounds; also, there is no space after the comma (,). Also, in previous versions of the Laravel framework, we could use Inf as an upper bound to indicate that their is no upper bound. In Laravel 5.5, you must use an asterisk (*); using the Inf constant will no longer work. We discuss ranges in greater detail in the next section.

#Ranges

Laravel's translation components allow for a simple way to express ranges of numbers when defining language files; we've seen many of the ways to do this in previous sections. However, we will explore them again in this section.

#Creating a Range Between Two Numbers

To create a range between two numbers, enclose the range in square brackets ([ and ]) with the following format:

1[<LOWER_BOUNDS>,<UPPER_BOUNDS>]

Where <LOWER_BOUNDS> is the lower bounds of the range, and <UPPER_BOUNDS> is the upper bounds of the range. We will create a language file at resources/lang/en/plural.php:

1<?php
2 
3return [
4 
5 'ranges' =>
6 
7 '{0}No items
8 |[1,3]Between one and three
9 |[4,6]Between four and six
10 |[7,*]Seven and beyond!'
11 
12];

The following table lists the input number and the translation line result:

Input Number Result
0 No items
2 Between one and three
3 Between one and three
4 Between four and six
6 Between four and six
7 Seven and beyond!
823 Seven and beyond!

#Creating Negative Ranges

We could also create a range for all numbers less than zero:

1<?php
2 
3return [
4 
5 'ranges' =>
6 
7 '{0}No items
8 |[1,3]Between one and three
9 |[4,6]Between four and six
10 |[7,*]Seven and beyond!
11 |[*,-1]Less than zero'
12 
13];

The following table lists some sample input and output:

Input Number Result
-1 Less than zero
0 No items
2 Between one and three
3 Between one and three
4 Between four and six
6 Between four and six
7 Seven and beyond!
823 Seven and beyond!

You may also notice that we placed or negative range at the end of the translation line; this is due to the way the MessageSelector handles rule parsing.

Some absolutely amazing
people

The following amazing people help support this site and my open source projects ♥️
If you're interesting in supporting my work and want to show up on this list, check out my GitHub Sponsors Profile.