-
-
Notifications
You must be signed in to change notification settings - Fork 29
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
New feature: Translation message placeholder support #121
base: 2.27.x
Are you sure you want to change the base?
Conversation
Signed-off-by: Kevin Hamilton <[email protected]>
Signed-off-by: Kevin Hamilton <[email protected]>
Signed-off-by: Kevin Hamilton <[email protected]>
Signed-off-by: Kevin Hamilton <[email protected]>
Signed-off-by: Kevin Hamilton <[email protected]>
Signed-off-by: Kevin Hamilton <[email protected]>
Signed-off-by: Kevin Hamilton <[email protected]>
Signed-off-by: Kevin Hamilton <[email protected]>
e020ffa
to
1306a09
Compare
@TotalWipeOut Some comments:
A placeholder is in the message: "Hello {name}!" and the process of converting the message with a placeholder can be called formatting or replacement. To format or replace the placeholders, values/parameters are required.
Hijacking is not an option because:
My first thought was, why allow multiple variants when one official is enough, but if we see this component in use with different frameworks or CMS, this would be a benefit.
Why not? We can update the view helper configuration to use the new view helpers with parameter support: laminas-i18n/src/ConfigProvider.php Lines 151 to 158 in b3259ac
And the new view helper(s) can be used like this: <?= $this->translate($message, params: ['name' => 'World']) ?> The old view helpers must be retained for reasons of backward compatibility. |
@froschdesign The reason for multiple placeholder formats is that while I agree ICU message format is the place to be, i wanted the ability to allow this feature to integrate with existing apps with existing translation files that might do it in the various other ways via custom solutions. The app I work on uses printf format for this task currently Should I add a new method in Regarding view helpers, from your example, can you show me how this will work with a new view helper, but called the same in the view and it not being a BC break? I don't fully understand Thanks again for your detailed response ❤️ |
This is a simple mapping: $renderer = new Laminas\View\Renderer\PhpRenderer();
$renderer->getHelperPluginManager()->configure(
(new Laminas\I18n\ConfigProvider())->getViewHelperConfig()
);
$renderer->getHelperPluginManager()->setFactory(
NewTranslate::class,
Laminas\ServiceManager\Factory\InvokableFactory::class
);
$renderer->getHelperPluginManager()->setAlias(
'translate',
NewTranslate::class
);
echo $renderer->translate('example', params: ['foo' => 'bar']); This overwrites the existing view helper, as is done if you want to use your own. |
@froschdesign So i understand correctly with this approach, this functionality requires additional config in the app, add wont work out of the box? |
This component already provides a configuration: laminas-i18n/src/ConfigProvider.php Lines 151 to 198 in b3259ac
This must be extended so that the new view helper(s) can be used.
No, because a new view helper must be created and the old one remains as it is. (The view helpers are not marked as final, so we cannot change them.)
No, nothing must and will be changed in this case. Via the configuration we will map
This works out of the box. Please look at the renderer of laminas-view: |
…lpers Signed-off-by: Kevin Hamilton <[email protected]>
Signed-off-by: Kevin Hamilton <[email protected]>
5a8b9f5
to
de5e914
Compare
@froschdesign Thanks - I have tried to address your feedback :) |
Signed-off-by: Kevin Hamilton <[email protected]>
Signed-off-by: Kevin Hamilton <[email protected]>
@froschdesign Let me know if this is something your happy to be included in this library, and i will get the tests written. Thanks |
@TotalWipeOut
Short: The feature is definitely necessary, but with a modified implementation. Minor ReleaseIf we add this feature in a minor release then without any changes on the Examplenamespace Laminas\I18n\Translator\Formatter;
use Laminas\I18n\Translator\Translator;
use Laminas\I18n\Translator\TranslatorInterface;
final class TranslatorFormatterDecorator implements TranslatorInterface
{
public function __construct(
private readonly Translator $translator,
private readonly FormatterInterface $formatter
) {
}
public function translate(
$message,
$textDomain = 'default',
$locale = null,
iterable $parameters = []
): string {
// …
}
public function translatePlural(
$singular,
$plural,
$number,
$textDomain = 'default',
$locale = null,
iterable $parameters = []
): string {
// …
}
} Benefits
More Informations
Major ReleaseHere we can change the interface for the translator and rework the entire So if you can wait, the next major version is an option. |
Not entirely true: "Originally posted by @thexpand at zendframework/zend-i18n#104" (See: #7) |
|
||
use function str_replace; | ||
|
||
class HandlebarPlaceholder implements PlaceholderInterface |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The naming is still wrong because it is an formatter which formats a message. A placeholder is in the message: "Hello {name}!" – here {name}
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@froschdesign so then from this, shall i rename things like this:
- namespace to be
Laminas\I18n\Translator\Formatter
PlaceholderPluginManager
toFormatterPluginManager
, same with factoryPlaceholderInterface
toFormatterInterface
- and all class suffixes to
*Formatter
or, if you have something else in mind, please advise
Oh yes, thanks for spotting that. |
Signed-off-by: Kevin Hamilton <[email protected]>
Signed-off-by: Kevin Hamilton <[email protected]>
d4db28e
to
da1f695
Compare
Signed-off-by: Kevin Hamilton <[email protected]>
View\Helper\TranslateWithParams::class => InvokableFactory::class, | ||
View\Helper\TranslatePluralWithParams::class => InvokableFactory::class, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will provide the delegator to add the decorator for the new view helpers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, I was going to ask regarding that. That would be great.
Thanks for all your time on this!
Co-authored-by: Frank Brückner <[email protected]> Signed-off-by: Kevin Hamilton <[email protected]>
Signed-off-by: Kevin Hamilton <[email protected]>
Signed-off-by: Kevin Hamilton <[email protected]>
Description
WORK IN PROGRESS
Upon needing message placeholders and seeing the 4 year old issue #7 about needing it, I decided to take a stab at adding message placeholder support into laminas-i18n, as I see it as key missing feature.
(I decided to use the term 'placeholders' instead of 'parameters' so that it is less ambiguous)
As I really didn't want a BC break, I have hijacked the$textDomain
parameter of thetranslate
/translatePlural
method to allow passing in placeholders where it seemed most logical going forward. There is a way to be able to provide bothtextDomain
andplaceholders
if that's needed.Goals
What I've done so far
Translator\TranslatorServiceFactory
to inject a placeholder from configTranslator\Translator
class to add new methods that pass messages through a placeholder compiler before returningTODO
Before i go any further, I am seeking advice as to if this is the correct approach for adding this without a bc break
The code is not perfect, so any guidance on naming/architecture/design would be amazing. Once i have some feedback, i will make any required changes and get on with the tests
And, a thank you to everyone in the Laminas community for being so kind and generous with your time ❤️