Login to bookmark this video
Buy Access to Course
06.

Placeholders and Pluralization

|

Share this awesome video!

|

Keep on Learning!

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

Onward! Let's find a complex translation scenario. On the article page, scroll down and find the comments section. This "3 Comments" header is dynamic, the number changes based on the comment count.

Find this text in templates/article/show.html.twig. Here's the dynamic value: comments|length. You might think to just translate "Comments" and not worry about the dynamic part, but certain languages might have alternate word order variations. Like "3 Comments" in English versus "Comments 3" in a different language. So, we need the translation text to include the dynamic part.

How do we handle this? Translation placeholders to the rescue!

Translation Placeholders

Clear out all this text, and come up with a key: since we're in article/show.html.twig, use article.show.comments. Add |trans, and as the first argument of the filter, add an array. This is a key-value array, where the key is the placeholder, and the value is the dynamic value. For the key, use %count%. Keys wrapped in %'s are a standard Symfony convention. For the value, use comments|length:

95 lines | templates/article/show.html.twig
// ... lines 1 - 4
{% block body %}
// ... lines 6 - 44
<div class="bg-white rounded-lg py-10 mt-5 px-5 lg:px-0">
<div class="article-text max-w-4xl mx-auto">
// ... lines 47 - 55
<h3 class="my-6 text-2xl font-medium"><i class="pr-3 fa fa-comment"></i>{{ 'article.show.comments'|trans({'%count%': comments|length}) }}</h3>
// ... lines 57 - 83
</div>
</div>
// ... lines 86 - 87
{% endblock %}
// ... lines 89 - 95

Now, open our messages.en.yaml file and add the new key, article: show: comments:. For the value, use %count% Comments:

7 lines | translations/messages.en.yaml
// ... lines 1 - 3
article:
show:
comments: '%count% Comments'

Most translation services know to ignore text in %'s, so you shouldn't need to worry about "count" accidentally being translated.

Back to the app and refresh. Nothing super exciting but it is working!

Let's make sure it changes dynamically. Back in show.html.twig, temporarily replace comments|length with just 1:

95 lines | templates/article/show.html.twig
// ... lines 1 - 4
{% block body %}
// ... lines 6 - 44
<div class="bg-white rounded-lg py-10 mt-5 px-5 lg:px-0">
<div class="article-text max-w-4xl mx-auto">
// ... lines 47 - 55
<h3 class="my-6 text-2xl font-medium"><i class="pr-3 fa fa-comment"></i>{{ 'article.show.comments'|trans({'%count%': 1}) }}</h3>
// ... lines 57 - 83
</div>
</div>
// ... lines 86 - 87
{% endblock %}
// ... lines 89 - 95

Refresh the page, and great! "1 Comments". But, hmm, maybe it's not the end of the world, but this should really read "1 Comment" - without the "s".

Pluralization

Back in messages.en.yaml, at the beginning of the value, add 1 Comment|:

7 lines | translations/messages.en.yaml
// ... lines 1 - 3
article:
show:
comments: '1 Comment|%count% Comments'

This pipe (|) signals to Symfony that you have multiple versions for pluralization. Go back and refresh the page, and it now correctly displays "1 Comment". Make sure it still works with more than one comment by switching back to comments|length in show.html.twig:

95 lines | templates/article/show.html.twig
// ... lines 1 - 4
{% block body %}
// ... lines 6 - 44
<div class="bg-white rounded-lg py-10 mt-5 px-5 lg:px-0">
<div class="article-text max-w-4xl mx-auto">
// ... lines 47 - 55
<h3 class="my-6 text-2xl font-medium"><i class="pr-3 fa fa-comment"></i>{{ 'article.show.comments'|trans({'%count%': comments|length}) }}</h3>
// ... lines 57 - 83
</div>
</div>
// ... lines 86 - 87
{% endblock %}
// ... lines 89 - 95

Refresh the app, and yep, the pluralization works! Symfony knows to use the 1 Comment version when the count is 1, and the %count% Comments version when the count isn't 1.

ICU MessageFormat

It's worth noting that Symfony supports the official ICU MessageFormat.

To enable it, you need to adjust the filenames of your translation files to add this +intl-icu text.

Placeholders are handled a bit differently. In the translation text, wrap the placeholder key in curly braces. Then, when passing the placeholder key, you don't need to wrap it in anything.

There's also a powerful condition system. This example shows how you can change the message based on a gender placeholder.

Pluralization is also more powerful. You can use the condition system to create really fine-grained pluralization rules.

Something to check out if you need it, but for now, we'll stick with the basic system.

Next, we'll look at how to handle translation text that contains HTML.