November 30, 2016 —John Koster
Since Laravel's translator is build on top of Symfony's translator component, the syntax rules used by Symfony's pluralization system will work with Laravel. Pluralization translation lines follow the ISO 31-11 standard for numeric intervals, such as specific numbers and ranges. The syntax also allows for "tags", which behave like comments for different plural translation messages.
Message tags act as a sort of comment to help explain the various translation messages when dealing with pluralization. Tags appear at the beginning of a translation message, contain no spaces and end with one colon character (:
). The following code example highlights the usage of tags:
1<?php2 3return [4 5 'books' => 'first_message_tag: There is one book.|'.6 'second_message_tag: There are :count books.',7];
Message tags are ignored when returning the appropriate message for a given plural form of a message. This can be observed in the following code example (the result of the function call will appear above the function call as a comment):
1<?php2 3// There is one book.4trans_choice('plural.books', 1);5 6// There are 4 books.7trans_choice('plural.books', 4, ['count' => 4]);
Sometimes it is useful to associate a given message number with exactly one number. All of the previous examples have not dealt with the pluralization case when there is no items (when the $number
is exactly 0
).
Passing 0
to the previous translation messages would produce the following result:
1There are 0 books.
However, it is sometimes desirable to handle the case explicitly and return a more appropriate message:
1<?php 2 3// Sorry! No books here. 4trans_choice('{0} Sorry! No books here. 5 |There is one book. 6 |There are :count books.', 0); 7 8// There is one book. 9trans_choice('{0} Sorry! No books here.10 |There is one book.11 |There are :count books.', 1);12 13// There are 2 books.14trans_choice('{0} Sorry! No books here.15 |There is one book.16 |There are :count books.', 2);
It can be seen in the last call to the trans_choice
function in the above code example that Laravel will automatically replace the :count
placeholder with the $number
of items. Because of this, the two function calls are identical in their result:
1<?php 2 3// There are 2 books. 4trans_choice('{0} Sorry! No books here. 5 |There is one book. 6 |There are :count books.', 2); 7 8// There are 2 books. 9trans_choice('{0} Sorry! No books here.10 |There is one book.11 |There are :count books.', 2,12 [13 'count' => 214 ]);
The following table will show more examples of handling specific numbers when dealing with pluralization translation. The table will use the following translation message:
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 | Raises an error |
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, an instance of InvalidArgumentException
will be thrown. The exception message will explain that it was unable to choose a translation. However, a very small fix will allow this to work.
To get the desired result, prefix the entire translation message with a single pipe (|
) character:
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!
Now, the following function call will return the expected result:
1<?php 2 3$message = '|{0} There are no books! 4 |{1,2,3} You have one, two or three books. 5 |{4} Four is a great number of books! 6 | The number of books you have is uncountable!'; 7 8// The number of books you have is uncountable! 9trans_choice($message, 5);10 11// The number of books you have is uncountable!12trans_choice($message, 50);13 14// The number of books you have is uncountable!15trans_choice($message, 100);16 17// The number of books you have is uncountable!18trans_choice($message, M_EULER);19 20// The number of books you have is uncountable!21trans_choice($message, INF);
Specifying every number required for a given translation message can be tedious, or even impossible. However, intervals can be specified to make working with large groups of numbers easier. The syntax for intervals comes directly from the ISO 31-11 standard. Intervals are written as a pair of numbers between two delimiters (a delimiter for both the left and right).
There are two types of delimiters: inclusive and exclusive. Inclusive delimiters include the number that it is associated with and an exclusive delimiter excludes the number that it is associated with. The style of writing inclusive and exclusive delimiters depends on whether or not the delimiter appears on the left or the right of an interval.
Delimiter Position | Inclusive Form | Exclusive Form |
---|---|---|
Left | [ |
] |
Right | ] |
[ |
The following code example demonstrates how to write an interval for all numbers between one and ten, including numbers one and ten:
1[1,10]
The following example would not allow the numbers one and ten:
1]1,10[
As shown in the above examples, the endpoints (the two numbers) of the interval are separated by a comma ,
. The standard technically allows the endpoints to be separated by a semicolon, but the implementation used by the translator does not support this.
The following table contains various intervals and the numbers that they match:
Interval | Matching Values |
---|---|
[1,5] |
1 2 3 4 5 |
]1,5[ |
2 3 4 |
]5,10] |
6 7 8 9 10 |
[4,9[ |
4 5 6 7 8 |
[-Inf,+Inf] |
All numbers |
]-Inf,+Inf[ |
All numbers |
[20,+Inf] |
All numbers twenty and above |
[-Inf,20] |
All numbers twenty and below |
When using intervals with translation messages, the interval appears as the beginning of translation message. Message tags cannot be used when using intervals. The following is an example translation message using intervals:
1|{0} There are no books!2|[1,3] You have one, two or three books.3|{4} Four is a great number of books!4|[5,+Inf] The number of books you have is uncountable!
THe following code example will demonstrate the value returned by the trans_choice
helper function using the above translation message. The result will appear above the function call as a comment.
1<?php 2 3$message = '|{0} There are no books! 4 |[1,3] You have one, two or three books. 5 |{4} Four is a great number of books! 6 |[5,+Inf]The number of books you have is uncountable!'; 7 8// There are no books! 9trans_choice($message, 0);10 11// You have one, two or three books.12trans_choice($message, 2);13 14// Four is a great number of books!15trans_choice($message, 4);16 17// The number of books you have is uncountable!18trans_choice($message, 5);19 20// The number of books you have is uncountable!21trans_choice($message, 500);22 23// The number of books you have is uncountable!24trans_choice($message, 20000);25 26// The number of books you have is uncountable!27trans_choice($message, 1000000);28 29// The number of books you have is uncountable!30trans_choice($message, 154141162141166145154);
In the previous example, trying to match the number 3.4
will throw an instance of InvalidArgumentException
. To match any possible number, including decimals, for the previous translation messages, the explicit number groups must be replaced with intervals (to have the example make sense contextually, it will use USD currency instead):
1<?php 2 3$message = '|{0} You have no money. 4 |]0,1[ You have a few cents. 5 |[1,3[ You have a dollar, and some cents. 6 |[2,3[ You have a few dollars. 7 |[3,+Inf] Keep it up!'; 8 9// You have no money.10trans_choice($message, 0);11 12// You have a few cents.13trans_choice($message, 0.23);14 15// You have a dollar, and some cents.16trans_choice($message, 1.23);17 18// You have a few dollars.19trans_choice($message, 2.32);20 21// Keep it up!22trans_choice($message, 3);
∎
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.