Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Translation] added support for adding custom message formatter #18314

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 12, 2017

Conversation

aitboudad
Copy link
Contributor

@aitboudad aitboudad commented Mar 25, 2016

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? yes
Tests pass? yes
Fixed tickets #6009, #10152, one item in #11742, #11948
License MIT
Doc PR ~

{
@trigger_error('The '.__METHOD__.' method is deprecated since version 3.1 and will be removed in 4.0. Use trans instead.', E_USER_DEPRECATED);

$parameters['__number__'] = $number;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One possible BC break: we need to preserve number argument for the transChoice

@Nicofuma
Copy link
Contributor

What will be the replacement for $translator->transChoice('some_message2', 10, array('%count%' => 10)); ?

$translator->trans('some_message2', ['__number__' => 10, '%count%' => 10], null, null, TransChoiceMessageFormatter::NAME); ?

It looks a bit weird to me. I think that if trans and transChoice are merged together we should have a way to automatically choose between the 2 (maybe automatically takes a '%count%' key is their isn't any '__number__' one or something like that?)

@aitboudad
Copy link
Contributor Author

@Nicofuma merging them together looks better!

@linaori
Copy link
Contributor

linaori commented Mar 25, 2016

How would you envision this in the templates? Adding class names/constants is pretty annoying in twig. It also means that I have to pass a lot of default values if I want to specify that. It feels like you have a lot more boilerplate to achieve the same. Having to write down __number__ doesn't feel ideal either but having to rely on another pre-defined key is kind of magic as well.

What I know from experiences:

  • For transchoice, you always have to define a number
  • specifying the domain and locale is kind of annoying for most cases for the solution you present (messages domain/default locale)
  • A lot of times I translate without parameters but with a different domain

So I think we can agree that something is bothersome in the current implementation but i don't think the solution you present will solve it and will possibly even decrease the DX.

@aitboudad
Copy link
Contributor Author

Using multiple formatter is something rare but this allow us to migrate safely to IntlMessageFormatter.
Right now if we combine trans with transChoice in one formatter it'll reduce some boilerplate,

__number__ is provider for only BC break not for end-users, we can use %count% like we did in twig transChoice

{{ 'Hello world'|transchoice(count) }} //Before
{{ 'Hello world'|trans({ '%count%': count }) }} // After

@linaori
Copy link
Contributor

linaori commented Mar 25, 2016

So how would that be determined? I can have a %count% in my arguments without it being a transchoice.

$translator->trans($v, ['%count%' => 10], null, null, TransChoiceMessageFormatter::NAME);
// vs
$translator->transChoice($v, 10);

Where would it be less boilerplate? Maybe I missed something?

@aitboudad
Copy link
Contributor Author

@iltar

So how would that be determined? I can have a %count% in my arguments without it being a transchoice.

agreed we should find another pre-defined key :/

Where would it be less boilerplate? Maybe I missed something?

As I said before TransChoiceMessageFormatter will be meged into TransMessageFormatter so we don't need to pass the formatter argument by default but we need to rely on a pre-defined key

@HeahDude
Copy link
Contributor

What about trans_count ?

@linaori
Copy link
Contributor

linaori commented Mar 25, 2016

Ah okay, so it's the part where the key defines what type is used. In php you could use a constant but that would be cumbersome in twig. You could expose the value like {{ 'foo' | trans({trans.count: 10}) }}.

Something else that popped my mind, simply no key: $translator->trans('foo', [10]). Sadly it's typehinted as array for this case. In twig it could be {{ 'foo' | trans(10) }} though.

@javiereguiluz
Copy link
Member

At first glance this looks to me like a serious step back in DX:

{# before #}
{{ 'Hello world'|transchoice(count) }}

{# after #}
{{ 'Hello world'|trans({ '%count%': count }) }}
// before
$translator->transChoice('some_message2', 10, array('%count%' => 10));

// after
$translator->trans('some_message2', [TransMessageFormatter::TRANS_CHOICE => 10]);

My questions: What's wrong with the current transChoice() method? What's the problem we're trying to solve? Why the new code is longer to type and harder to learn? Thanks!

@mvrhov
Copy link

mvrhov commented Mar 29, 2016

@javiereguiluz: take a look at how message formatter class works.
This is what aitboudad would like to support.

@javiereguiluz
Copy link
Member

@mvrhov yes, but I'd prefer if we first focus on the before/after changes for end users and then we care about the internal implementation. For now I feel that this proposal is worse than the current situation.

@aitboudad
Copy link
Contributor Author

@javiereguiluz having 2 fonctions that achieve the same behavior looks wrong to me
and I think tranchoice will be useless for custom formattter such as IntlMessageFormatter or ExpressionsMessageFormatter. The main goal for me is to make IntlMessageFormatter as default formatter.

we can keep tranchoice as a helper method but IMO it shouldn't be part of TranslatorInterface
if you have any suggestions I would be happy to implement it ;)

@linaori
Copy link
Contributor

linaori commented Mar 30, 2016

@aitboudad Actually the only times I've used the transchoice, I've done so via twig and never in the code. I find it a rare occasion having to use the translator directly in the code in the first place (but does happen).

@javiereguiluz
Copy link
Member

@aitboudad here it is how Translator works today from the controller and the templates:

// simple
$this->get('translator')->trans('Hello');

// placeholders
$this->get('translator')->trans('Hello %name%', ['%name%' => 'Fabien']);

// pluralization
$this->get('translator')->transChoice(
    'There is one apple|There are %count% apples',
    10,
    array('%count%' => 10)
);

// selecting the catalogue
$this->get('translator')->trans('Hello', [], 'admin');

// selecting the locale
$this->get('translator')->trans('Hello', [], 'messages', 'fr_FR');
{# simple #}
{% trans %}Hello{% endtrans %}
{{ 'Hello'|trans }}

{# placeholders #}
{% trans with { '%name%': 'Fabien' } %}Hello %name%{% endtrans %}
{{ 'Hello'|trans({'%name%': 'Fabien'}) }}

{# pluralization #}
{% transchoice count %}
    {0} There are no apples|{1} There is one apple|]1,Inf[ There are %count% apples
{% endtranschoice %}

{{ '{0} There ...|{1} There ...'|transchoice(count) }}

{# selecting the catalogue #}
{% trans from 'admin' %}Hello{% endtrans %}
{{ 'Hello'|trans({}, 'app') }}

{# selecting the locale #}
{% trans into 'fr_FR' %}Hello{% endtrans %}
{{ 'Hello'|trans({}, 'messages', 'fr_FR') }}

Please, provide the equivalent examples for the new way of using the Translator that you are proposing, so we can compare. Thanks!

@aitboudad
Copy link
Contributor Author

@javiereguiluz
For php:

 // pluralization
+ use Symfony\Component\Translation\Formatter\TransMessageFormatter;
+
-$this->get('translator')->transChoice(
+$this->get('translator')->trans(
     'There is one apple|There are %count% apples',
-    10,
-    array('%count%' => 10)
+    array(TransMessageFormatter::TRANS_CHOICE => 10)
 );

in Twig (I defined global variable transchoice = TransMessageFormatter::TRANS_CHOICE):

 {# pluralization #}
-{% transchoice count %}
+{% trans with { transchoice: count } %}
     {0} There are no apples|{1} There is one apple|]1,Inf[ There are %count% apples
-{% endtranschoice %}
+{% endtrans %}

-{{ '{0} There ...|{1} There ...'|transchoice(count) }}
+{{ '{0} There ...|{1} There ...'|trans({transchoice: count}) }}

@javiereguiluz
Copy link
Member

@aitboudad thanks for the info. I've updated your comment to add the missing use import.

Does the new system mean that %count% is a hardcoded variable name in translation messages? If not, how could we implement this example with the new proposal?

$this->get('translator')->trans(
    'There is one apple|There are %num% apples', 5, ['%num%' => 'five']
);

@aitboudad
Copy link
Contributor Author

@javiereguiluz

$this->get('translator')->trans(
    'There is one apple|There are %num% apples',
    array(TransMessageFormatter::TRANS_CHOICE => 5, '%num%' => 'five')
);

we can still using %count%:

$this->get('translator')->trans(
    'There is one apple|There are %count% apples',
    array(TransMessageFormatter::TRANS_CHOICE => 5, '%count%' => 'five')
);

$name = $name ?: $this->defaultFormatter;

foreach ($this->formatters as $formatter) {
if ($name === $formatter->getName()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't you store the name as array key when registering?
This loop will be executed for every trans() call!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed thanks!

@aitboudad aitboudad force-pushed the translation-formatters branch from cef7950 to 1d4343c Compare July 5, 2016 15:45
@aitboudad aitboudad changed the title [WIP][Translation] allow using multiple formatters with decoupling the def… [Translation] allow using multiple formatters with decoupling the default one. Jul 5, 2016
@aitboudad aitboudad force-pushed the translation-formatters branch from 1d4343c to 1660808 Compare July 5, 2016 15:47
@aitboudad
Copy link
Contributor Author

@nicolas-grekas you can push now!

@nicolas-grekas nicolas-grekas force-pushed the translation-formatters branch 4 times, most recently from ee13182 to f8b9760 Compare August 5, 2017 19:12
@aitboudad aitboudad force-pushed the translation-formatters branch from f8b9760 to a78ab4e Compare August 5, 2017 19:20
@nicolas-grekas
Copy link
Member

@aitboudad thanks, I just push forced one last time, addressing a few minor things meanwhile.

@nicolas-grekas nicolas-grekas force-pushed the translation-formatters branch from a78ab4e to 504bcb8 Compare August 5, 2017 19:41
@@ -28,6 +28,13 @@
<tag name="monolog.logger" channel="translation" />
</service>

<service id="translator.formatter" alias="translator.formatter.default" />
<service id="Symfony\Component\Translation\Formatter\MessageFormatterInterface" alias="formatter" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alias="translator.formatter"?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed thanks

@nicolas-grekas nicolas-grekas force-pushed the translation-formatters branch from 504bcb8 to 34ff232 Compare August 5, 2017 20:48
@nicolas-grekas
Copy link
Member

I think this PR is ready to merge, failures are false positives.
@aitboudad would you be able to work on a doc PR if worth it?

@aitboudad
Copy link
Contributor Author

why not :), I'll try to work on it next weekend.

@aitboudad
Copy link
Contributor Author

@nicolas-grekas I missed to mention the doc PR #8284, I guess the PR is ready to merge.

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xabbuh I'll let you merge if you don't mind

UPGRADE-3.4.md Outdated
* Passing a `Symfony\Component\Translation\MessageSelector` to `Translator` has been
deprecated. You should pass a message formatter instead

Before:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noticed: This line and the following need to be indented by an additional space so that it will be rendered property as part of the list item.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@@ -28,6 +28,12 @@
<tag name="monolog.logger" channel="translation" />
</service>

<service id="translator.formatter" alias="translator.formatter.default" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this? I mean this is just redundant with what we do in the extension (in combination with the default option value).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, in fact there is one difference: The alias registered in the extension is private. So IMO that's a good argument to remove this one here. At least it will avoid confusion when reading the code.

Copy link
Member

@nicolas-grekas nicolas-grekas Sep 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this one also is private, all our XML files start with public="false" as default ;) )

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm okay 😆

Copy link
Contributor Author

@aitboudad aitboudad Sep 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the default value can be overridden throughout the config, without using the alias we can't inject the default one if we need it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we always create the alias in https://github.com/aitboudad/symfony/blob/fd9f484879a08e00a42a3888d8b1681923b8eb0b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php#L1078, don't we ($config['formatter'] will have the default value if the user didn't provide any)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right, removed!

@aitboudad aitboudad force-pushed the translation-formatters branch from 0050eb1 to fd9f484 Compare September 12, 2017 10:57
@@ -234,6 +234,27 @@ Translation
and will be removed in 4.0, use `Symfony\Component\Translation\Writer\TranslationWriter::write`
instead.

* Passing a `Symfony\Component\Translation\MessageSelector` to `Translator` has been
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably be added to the component's changelog file too. And we also need to update the UPGRADE-4.0.md file accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@aitboudad aitboudad force-pushed the translation-formatters branch from fd9f484 to 42183b0 Compare September 12, 2017 12:17
@xabbuh
Copy link
Member

xabbuh commented Sep 12, 2017

Thank you @aitboudad.

@xabbuh xabbuh merged commit 42183b0 into symfony:3.4 Sep 12, 2017
xabbuh added a commit that referenced this pull request Sep 12, 2017
…formatter (aitboudad)

This PR was merged into the 3.4 branch.

Discussion
----------

[Translation] added support for adding custom message formatter

| Q | A |
| --- | --- |
| Branch? | master |
| Bug fix? | no |
| New feature? | yes |
| BC breaks? | no |
| Deprecations? | yes |
| Tests pass? | yes |
| Fixed tickets | #6009, #10152, one item in #11742, #11948 |
| License | MIT |
| Doc PR | ~ |

Commits
-------

42183b0 [Translation] Support adding custom message formatter
@aitboudad aitboudad deleted the translation-formatters branch September 12, 2017 12:39
This was referenced Oct 18, 2017
javiereguiluz added a commit to symfony/symfony-docs that referenced this pull request Sep 24, 2019
… (aitboudad)

This PR was merged into the 3.4 branch.

Discussion
----------

[Translation] add how to create custom message formatter.

| Q | A |
| --- | --- |
| Doc fix? | no |
| New docs? | yes |
| Applies to | 3.4 |
| Fixed tickets | symfony/symfony#18314 |

Commits
-------

02f31ac [Translation] create custom message formatter.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.