Back to Course |
Multi-Language Laravel 11: All You Need to Know

Translating Plural/Singular Forms

Have you ever needed counting specific items, with translations?

A typical code would be:

<div class="">
@if($messagesCount === 0)
<span>You have no new messages</span>
@elseif($messagesCount === 1)
<span>You have 1 new message</span>
@else
<span>You have {{ $messagesCount }} new messages</span>
@endif
</div>

To avoid these if conditions, you can use the Laravel localization pluralization feature.


Using trans_choice() Helper

Laravel comes with a really great helper function called trans_choice(). This function allows us to use a string that contains multiple translations, and it will choose the correct one based on the number we pass to it.

The rules:

  • Use the | character to separate the different count options.
  • Use the :count to get the number we passed to the function.
  • Use {INT} to specify for which number we want to use this translation.
  • Use [INT,*] to specify for which number we want to use this translation, and all the numbers after it.

Example:

{0} You have no new messages|{1} You have 1 new message|[2,*] You have :count new messages

  • {0} You have no new messages - This will be used when the number is 0.
  • {1} You have 1 new message - This will be used when the number is 1.
  • [2,*] You have :count new messages - This will be used when the number is 2 or more.

And all we have to do is call the trans_choice() with a key to our translation and count of some object (it can be a Countable object or a number).

Here are examples in both JSON and PHP:

Pluralization in JSON

JSON has support for this, but it's not that clean. Let's take a look:

lang/en.json

{
"{0} You have no new messages|{1} You have 1 new message|[2,*] You have :count new messages": "{0} You have no new messages|{1} You have 1 new message|[2,*] You have :count new messages"
}

In our blade we can use the following code:

View

{{ trans_choice('{0} You have no new messages|{1} You have 1 new message|[2,*] You have :count new messages', $messagesCount) }}

Bonus: There's also a Blade helper when working directly with Blade files - @choice() which does exactly the same:

{{ @choice('{0} You have no new messages|{1} You have 1 new message|[2,*] You have :count new messages', $messagesCount) }}

And it will react to the number of messages we have. But this requires us to write the same string in JSON and in our blade which is not very clean.

Pluralization in PHP

PHP has a better way to do this, and it's using the @choice directive. Let's take a look:

lang/en/messages.php

return [
'newMessageIndicator' => '{0} You have no new messages|{1} You have 1 new message|[2,*] You have :count new messages',
];

And now using it in the blade can look much nicer as we won't have to re-type the whole condition:

View

{{ trans_choice('messages.newMessageIndicator', $messagesCount) }}

OR

View

@choice('messages.newMessageIndicator', $messagesCount)

See how much cleaner this is? We have a specific key to a message, and we can use it in multiple places without having to re-type the whole condition as we did in the JSON example.