Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[Translation] Translate translatable parameters#41858

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation

@kylekatarnls
Copy link
Contributor

@kylekatarnlskylekatarnls commentedJun 25, 2021
edited
Loading

QA
Branch?5.4
Bug fix?no (I guess it's a feature)
New feature?yes
Deprecations?no
LicenseMIT

Considering unit test expectation showingSymfony est awesome ! there is something quite not so awesome in the fact that "awesome" is not translated. As it looks like we're trying to make a french sentence, it sounds to me that what we actually expect is to have the whole sentence translated including the parameters if they are themselves translatable.

So with the following code:

$message =newTranslatableMessage('Symfony is %what%!', ['%what%' =>newTranslatableMessage('awesome')]);echo$message->trans($translator,'fr');

And with all translations properly provided to the$translator, I expect:

Symfony est superbe !

Currently, we get:

Symfony est awesome !

jvasseur, sstok, and romaricdrigon reacted with thumbs up emoji
@ro0NL
Copy link
Contributor

see#41136

i agree being able to nest messages-as-params is nice (cc@sylfabre)

OskarStark reacted with thumbs up emoji

@sylfabre
Copy link
Contributor

@kylekatarnls I'm wondering if using a placeholder for "awesome" is a good practice in the first place for this example 🤔

A placeholder in a translation string is basically a parameter which place varies from one language to another. And it may be formatted differently too (like m/d/y vs d/m/y, or the decimal separator).

IMO, if the placeholder requires translation (and not just formatting) then you are actually splitting a sentence. You'll hit grammar issues (like plural issues) at some point.

I do believe that this unit test is misleading. But it should use another value for the placeholder like a name. For instance, turn'Symfony is %what%', ['%what%' => 'awesome'] into'%who% is the creator of Symfony, ['%who' => 'Fabien']

=> Do you have a real-world example where you would need to translate the placeholder?

cc@ro0NL

Warxcell reacted with thumbs up emoji

@kylekatarnls
Copy link
ContributorAuthor

kylekatarnls commentedJun 29, 2021
edited
Loading

Yes I have real-world examples where sub-sentences grammar is handled well (we have no issue because translators are aware, can use ICU format messages and context, number of languages is limited, etc.):

  • %name%: %value% key-pair with colon so you can translate the spacing for colon, the LTR/RTL or customize: to use something else, then name and value can be translatable strings or not-translatable strings in different contexts.
    • For instance:Task output: %status% => success/failure (translated) and here for helping translators and avoid broken sentences it helps to have the whole and not to split this with concatenation
  • Hello %civility% %name% => civility isMrs,Mr,Dr and is translated
  • An error occurred when %event% => translate event
  • The field "%field%" is invalid => translate field

And it may be formatted differently too (like m/d/y vs d/m/y, or the decimal separator)

Yes, andTranslatableMessage can embed a date and format it according to the locale and/or translation messages, I don't see the point, it's actually one of the case we now have to format first manually before passing it in a translation and that we could handle automatically with this PR.

@sylfabre
Copy link
Contributor

@kylekatarnls Thank you for the real-world use-cases. I get your point and it makes sense 👍

I think your PR should be merged first, and then I'll update mine#41136 to useTranslatableInterface implementations. What do you think?

@ro0NL
Copy link
Contributor

IIUC we don't nessecarily aim for eg.$translator->trans('Symfony is %what%!', ['%what%' => new TranslatableMessage('awesome')]);? Should we?

@kylekatarnls
Copy link
ContributorAuthor

@ro0NL My point is: if it's a "translatable message" as the class name stand for and we pass it as a parameter of an other translatable message, one may fairly expect:

  • to be translated with the same translator and locale as the parent string.
  • an exception because maybe as you say it's not aimed, so we might assume Symfony would require user to explicitly translate it before passing it, sounds overkill, but it's the non-ambiguous way.

But what is the point is just casting it to string silently (so you get the message ID)? What is the real case where you could expect the current behavior forTranslatableMessage passed as parameter?

@ro0NL
Copy link
Contributor

same as#41136, to me this is just another form of formatting parameters i'd say

as such the feature to me sounds like; translator supporting translatable parameters.

or put different, im not sureTranslatableMessage should build custom parameter semantics on-top.

@sylfabre
Copy link
Contributor

sylfabre commentedJul 2, 2021
edited
Loading

@ro0NL I had the same first reaction as you:$translator->trans('Symfony is %what%!', ['%what%' => new TranslatableMessage('awesome')]); makes no sense because it splits the sentence and this is a bad practice. Let's forget about this one.

That's why I asked@kylekatarnls for other use cases and it turns out that placeholder values fall into 3 categories:

  1. Basic values with no change like a first name
  2. Medium values that just need formatting like a date: I'm addressing it with[Translation] Separate parameters formatting #41136 and it was the only use-case I was aware of before discussing with@kylekatarnls
  3. Advanced values that also require translations like "Mr" in English vs "M" in French

Think of "Hello Mr Sylvain, it is 8AM so get up!" in en_US, and "Bonjour M. Sylvain, il est 8:00 alors lève-toi !" in fr_FR

The en_US translation string with its placeholders is:Hello %civility% %firstname%, it is %hour% so get up

  • %civility% is use-case 3
  • %firstname% is use-case 1
  • %hour% is use-case 2

@ro0NL
Copy link
Contributor

@ro0NL I had the same first reaction as you: $translator->trans('Symfony is %what%!', ['%what%' => new TranslatableMessage('awesome')]); makes no sense

well my first reaction was#41858 (comment) :D

my point is, shouldnt these 2-ways-of-doing-things be equivalent semantically spoken?

$message =newTranslatableMessage('Symfony is %what%!', ['%what%' =>newTranslatableMessage('awesome')]);echo$message->trans($translator,'fr');// vsecho$translator->trans('Symfony is %what%!', ['%what%' =>newTranslatableMessage('awesome')]);
jvasseur and sylfabre reacted with thumbs up emoji

@kylekatarnls
Copy link
ContributorAuthor

Formatting (like in#41136) in a single way (having only the locale) is different from translating using a translator service (so you can mock it, customize, having dynamic translations). So with the current implementation for parameter formatting, no it does not solve the issue about translating sub-strings.

See the following:

returnt('You will get %something% and %otherthing% when %event%', ['something' =>t('a T-shirt'),'otherthing' =>t('a cup'),'event' =>t('you will finish the contest'),]);

(returned value above to be translated later with some translator service and locale calculated somehow from user or any other way)

If something is 10 possible solutions, otherthing 10, and event 100, sorry for the "bad practice" but we won't send 10 000 strings to our translators for every single possible output.

That's the clear and intuitive way to build the message, and assuming#41136 is merged, you still have to wrap eacht() inside a special parameter object (which makes your code very noisy) and your object is still not aware of the translator service which breaks test-ability and you will have somehow to pass your service an other way (clearly poor solution). Without talking nested parameter in a second level.

About your second question, I'm not sure what you mean, currently both are possible and behave the same (TranslatableMessage is casted to string usinggetMessage()) This PR would change the result for both styles and I feel it's right. Can't see any reason to have different output.

@ro0NL
Copy link
Contributor

currently both are possible and behave the same

they do not. The casting is a side-effect, if we pass specific parameters and/or domain tonew TranslatableMessage('awesome') we'd lose it.

I think#41136 is on the right track, but instead ofif ($parameter instanceof ParameterInterface) { it could doif ($parameter instanceof TranslatableInterface) {. If eg. DateTranslatable ignores the $translator being passed, that's fine i'd say.

@kylekatarnls
Copy link
ContributorAuthor

Absolutely, if#41136 handlesTranslatableInterface, that resolves the issue.

@sylfabre
Copy link
Contributor

@ro0NL@kylekatarnls Are you guys working together to give me some work? 😅

More seriously, I'm okay with refactoring my PR to dropParameterInterface, and to stick withTranslatableInterface

@kylekatarnls
Copy link
ContributorAuthor

kylekatarnls commentedJul 4, 2021
edited
Loading

Hi guys, want to mention that my PR only add support for the interface in arguments, that's quite scoped to the strict minimum to support any implementation ofTranslatableInterface as parameter in user-land.

That's why I think it would be nice to have an other review from@nicolas-grekas now I fixed the first review's comments. And maybe him and@fabpot could give an opinion about this feature, says if it goes to 5.4 or 6 (then I would re-ajust the closure style).

The@sylfabre#41136 PR is going quite further as it also provides implementations for precise cases, add a new dependency, so before refactoring it to useTranslatableInterface instead of a new dedicated interface, I think it would be wise to wait for Symfony translation team to first accept or decline this one.

@ro0NL
Copy link
Contributor

I think it's important to keep $translator->trans the main entry point.

Contract definesarray $parameters An array of parameters for the message, thus ... we can do anything. In that sense i'd be OK if we experiment with eg.array<string, string|Stringable|TranslatableInterface> for the component's translator implmentation. We can argue it should be the parameter's contract yes.

sstok reacted with thumbs up emoji

@romaricdrigon
Copy link
Contributor

Hello,
I came here from#41882, to add that I had this exact use case, and I indeed up needing aNestedTranslatableMessage as in#41882. So having this feature in the framework would be amazing - either supported inTranslatableMessage base implementation as here, or in a more complexNestedTranslatableMessage. Maybe I can help move it forward in some way?

@sylfabre
Copy link
Contributor

Hello@ro0NL@kylekatarnls
What are the next steps here? How may I help to make it move forward?

The@sylfabre#41136 PR is going quite further as it also provides implementations for precise cases, add a new dependency, so before refactoring it to use TranslatableInterface instead of a new dedicated interface, I think it would be wise to wait for Symfony translation team to first accept or decline this one.

I'm 100% aligned with this ☝️

@kylekatarnls
Copy link
ContributorAuthor

@nicolas-grekas 🙏

Copy link
Member

@nicolas-grekasnicolas-grekas left a comment

Choose a reason for hiding this comment

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

Nobody can prevent splitting translatable strings into chunks that lead to grammar issues. This PR is not needed to follow that bad practice :)

Since there are legit use cases that have been described, and since this makes perfect sense from a technical pov (the raw message is dumped instead right now, which is worse), I'm good with the proposal.

sylfabre reacted with hooray emoji
@fabpot
Copy link
Member

Thank you@kylekatarnls.

@fabpotfabpotforce-pushed thefix/translate-translatable-parameters branch from37d52df toa31dff4CompareSeptember 10, 2021 07:32
@fabpotfabpot merged commit2221f4e intosymfony:5.4Sep 10, 2021
This was referencedNov 5, 2021
fabpot added a commit that referenced this pull requestDec 17, 2021
This PR was merged into the 6.1 branch.Discussion----------[Translation] Translatable parameters| Q             | A| ------------- | ---| Branch?       | 6.1| Bug fix?      | no| New feature?  | yes| Deprecations? | no| Tickets       | N/A| License       | MIT| Doc PR        | TBD✅  The TwigExtension now supports messages implementing `TranslatableInterface` (https://symfony.com/blog/new-in-symfony-5-2-translatable-objects).✅ Thanks to#41858, `TranslatableMessage` now supports recursive `TranslatableInterface` as params.❌ But using `TranslatableInterface` as params with regular messages is not supported yet.💡 This PR addresses this issue and makes it possible to create dedicated `TranslatableInterface` implementations like the one from#41136_Note: I would like also to add `TranslatableInterface` to the `trans(?string $id)` signature method like with the one from the [TwigExtension](https://github.com/symfony/symfony/blob/6.1/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php#L111) but I don't know how to do it without breaking BC. Any advice is welcome!_Commits-------5beaee8 [Translation] Translatable parameters
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@fabpotfabpotfabpot approved these changes

@nicolas-grekasnicolas-grekasnicolas-grekas approved these changes

+1 more reviewer

@sylfabresylfabresylfabre approved these changes

Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Projects

None yet

Milestone

5.4

Development

Successfully merging this pull request may close these issues.

7 participants

@kylekatarnls@ro0NL@sylfabre@romaricdrigon@fabpot@nicolas-grekas@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp