laminas / laminas-mvc-plugin-flashmessenger

Plugin for creating and exposing flash messages via laminas-mvc controllers
https://docs.laminas.dev/laminas-mvc-plugin-flashmessenger/
BSD 3-Clause "New" or "Revised" License
10 stars 16 forks source link

FlashMessenger translator does not support parameterised string #7

Closed weierophinney closed 2 years ago

weierophinney commented 4 years ago

The standard format (to my knowledge) of translating a string containing a variable would be:

<?= sprintf($this->translate(_("Ticket '%s' has been saved"), $ticket->getName()); ?>

The way FlashMessenger uses the Translator does not allow for such usage, and restricts the user to simple strings.

I extended the View\Helper\FlashMessenger to allow for the translator to sprintf() parameters into the string, but that required me to pass an array to the addMessage() like so:

$this->flashMessenger->setNamespace('xxx')->addMessage([ _("Ticket '%s' has been saved"), $ticket->getName() ]);

I recently did an composer update and it came to my attention now that the flashMessenger addMessage() function has changed it's definition to accept only strings.

Am I wrong on this? Should the FlashMessenger view helper be updated or could the addMessage definition become more loose?


Originally posted by @twmobius at https://github.com/zendframework/zend-view/issues/140

weierophinney commented 4 years ago

…the flashMessenger addMessage() function has changed it's definition to accept only strings.

Not explicitly:

public function addMessage($message, $namespace = null, $hops = 1)

https://github.com/zendframework/zend-mvc-plugin-flashmessenger/blob/843654a029a19c38e0c3b2e940e59edec75c3e4f/src/FlashMessenger.php#L155-L157


Originally posted by @froschdesign at https://github.com/zendframework/zend-view/issues/140#issuecomment-336389005

weierophinney commented 4 years ago

Yes you are right, not explicitly, but in the DocBlock the message is defined as string, which causes my IDE to flip out


Originally posted by @twmobius at https://github.com/zendframework/zend-view/issues/140#issuecomment-336390689

weierophinney commented 4 years ago

Sorry, I don't understand your problem.

_("Ticket '%s' has been saved") - what is this underscore character?

Why do not you use:

$this->translate(sprintf("Ticket '%s' has been saved", $ticket->getName()));

or

$flashMessenger->addMessage(sprintf("Ticket '%s' has been saved", $ticket->getName()));

Originally posted by @froschdesign at https://github.com/zendframework/zend-view/issues/140#issuecomment-336403830

weierophinney commented 4 years ago

The _() notation is a typical gettext notation, which allows gettext (and tools like poedit) to extract the strings from the source code. (See here: https://en.wikipedia.org/wiki/Gettext)

As for the second part of your question:

If I were to directly call the translator on the controller, before passing the string to the FlashMessenger, it would mean that I would have to inject the translator to the controller, or add a Translator controller plugin (which to my knowledge doesn't exists) thus negating the use of the translator in the FlashMessenger all together (and it would look awful)

Even if I used the translator view helper I would have to iterate all the messages from the FlashMessenger manually so as to translate them (in the view(!))

As for the second option you propose:

$flashMessenger->addMessage(sprintf("Ticket '%s' has been saved", $ticket->getName()));

In this case the message passed to the flashMessenger is "Ticket '123' has been saved" (considering that 123 is the name of the $ticket), thus when $this->translator->translate() is being called on the string, during the rendering of the FlashMessenger, no exact match will be found in the translation files (=no translation).


Originally posted by @twmobius at https://github.com/zendframework/zend-view/issues/140#issuecomment-336409404

weierophinney commented 4 years ago

The _() notation is a typical gettext notation, which allows gettext (and tools like poedit) to extract the strings from the source code.

I know Gettext, but this is not the question. Why do you use two translators?

  1. _()
  2. $translator->translate()

This irritates me.

In this case the message passed to the flashMessenger is "Ticket '123' has been saved"

Right, you must use:

sprintf($flashMessenger->addMessage("Ticket '%s' has been saved"), $ticket->getName());

Originally posted by @froschdesign at https://github.com/zendframework/zend-view/issues/140#issuecomment-336410452

weierophinney commented 4 years ago

There aren't two translators anywhere.

The _() is not a translator. I am just "marking" the strings so that gettext can extract them from the source code, so as to create the .po files required by the translator.

What I want is to pass strings with parameters to the FlashMessenger in sprintf() format, i.e.:

Ticket '%s' has been saved

as well as the parameters to substitute %s with after translating.

For that to work, the addMessage could perhaps expose another variable (i.e. $parameters) in the definition of the method, which the translate function could use like:

$item = $translator->translate( sprintf($item, $parameters), $translatorTextDomain );

Check here to see how the translator is currently being used by the View Helper.

Perhaps I am missing something really obvious here, or I am not explaining it properly (Sorry, English is not my native language)


Originally posted by @twmobius at https://github.com/zendframework/zend-view/issues/140#issuecomment-336419255

samsonasik commented 4 years ago

I transfered the issue. Now in laminas-mvc-plugin-flashmessenger

froschdesign commented 2 years ago

Duplicate of https://github.com/laminas/laminas-i18n/issues/7