-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Translation] Remove TranslatorBagInterface to allow for optimized caching in 3.0 #14530
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
Conversation
@@ -506,4 +522,19 @@ private function getConfigCacheFactory() | |||
|
|||
return $this->configCacheFactory; | |||
} | |||
|
|||
private function getCatalogueInternal($locale = null) |
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.
We could rename this back to getCatalogue()
and make it private once we do no longer implement TranslatorBagInterface
(in 3.0).
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.
can you add this note above.
@@ -213,54 +213,6 @@ public function testDifferentCacheFilesAreUsedForDifferentSetsOfFallbackLocales( | |||
$this->assertEquals('bar', $translator->trans('bar')); | |||
} | |||
|
|||
public function testPrimaryAndFallbackCataloguesContainTheSameMessagesRegardlessOfCaching() |
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.
it shoud be removed in 3.0
rename it into testLegacyPrimaryA..
instead and add
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
* | ||
* @author Matthias Pigulla <mp@webfactory.de> | ||
*/ | ||
interface FallbackLocaleAwareInterface |
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.
TranslatorLocaleAwareInterface
?
@@ -35,8 +35,8 @@ class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInter | |||
*/ | |||
public function __construct(TranslatorInterface $translator) | |||
{ | |||
if (!$translator instanceof TranslatorBagInterface) { | |||
throw new \InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface and TranslatorBagInterface.', get_class($translator))); | |||
if (!($translator instanceof TranslatorBagInterface && $translator instanceof FallbackLocaleAwareInterface)) { |
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.
requiring it to implement both is actually a BC break as not implementing FallbackLocaleAwareInterface was allowed previously. You are restricting the supported argument, and the BC promise only allows to widen it
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 right solution would be to provide a Translator implementation which would implement FallbackLocaleAwareInterface
on top of TranslatorBagInterface
and wrap the translator into this implementation when it implements TranslatorBagInterface but not FallbackLocaleAwareInterface. This would make things BC, avoid duplication between the DataCollectorTranslator and the LoggingTranslator and not have performance penalty for the normal case (given that the default translator implements the new interface)
@mpdude I just thought about another case where TranslatorBagInterface could be useful: https://github.com/willdurand/BazingaJsTranslationBundle/ is exposing translation catalogues to the JS code. Currently, it does that by reimplementing the loading itself (it gets all translation loaders from Symfony and gets all resources as well, all of which is done by the Translator) because TranslatorBagInterface was not available at that time. What would be the clean way toimplement such your case in your new architecture (duplicating the loading is not the clean way in the 2.6 architecture IMO, but it was probably the only way in the 2.3 architecture, which is why it is used) |
well I think we need to keep |
@stof In the case of messages available in both the primary and in fallback catalogues, which set of messages do you think this bundle would need? The problem is that if we burden We could, of course, internally use optimized structures for these methods plus a "complete" set of So, what if we had two different classes (or services in the case of the full-stack framework): The first one is where the resources and loaders are registered. You tell it your preferred order of locales, it will return a full-fledged The second one is the |
@mpdude This bundle would need anything needed to be able to reimplement And I agree that delegating all the loading to a separate class might be a better architecture. It could also simplify a bunch of things:
This is something I already thought about in the past. The hard part is the Translator class is currently designed to be extendable through inheritance. Extracting this logic into separate collaborators in a BC way will likely be very hard. |
@stof FYI I work on delegating all the loading :) |
@aitboudad have you found a way to keep BC for people overwriting protected methods of the Translator to customize the Translator through its current extension points ? |
@stof see an initial work for DelegationLoader I'll complete it soon, I think we need to deprecate |
What is the status of this PR? ping @aitboudad |
I rebased this branch and fixed the various issues from the first review by @aitboudad and @stof. This won't take us to the ultimate goal of a better and more efficient Anyway, this IMO improves our situation because we can (in 3.0) remove an interface that definetly is a show-stopper. |
@@ -39,6 +44,12 @@ public function __construct(TranslatorInterface $translator) | |||
throw new \InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface and TranslatorBagInterface.', get_class($translator))); |
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.
Need to fix that. The interface is deprecated and must not be required.
@fabpot ll try to finish #14622 today as I think it's more efficient than this one(ideally we should have something like https://github.com/openl10n/openl10n-translation/tree/master/src/Openl10n/Component/Translation/MessageCatalogue) |
…or a translation. That way, clients that need this information need no longer obtain the MessageCatalogues through the TranslatorBagInterface. This is a first step towards better encapsulation. Our final goal is to be able to use optimized implementations of the MessageCatalogue without leaking those to our clients.
…e on top of TranslatorBagInterface
@symfony/deciders I would like to ask for your vote on this. I believe that removing the TranslatorBagInterface is one important prerequisite for more efficient caching and/or loading inside the Translator because it improves encapsulation. With the current state of this PR, one important thing to note is that we leave clients without a way to retrieve the message catalogue from the translator, a feature added in 2.6 "by accident" (it would not have been necessary for the feature we added back then). To provide an alternate means of retrieving the catalogue is an on-going effort in #14622 and #14671, but with the internal structure of So, the decision you need to make is whether the improvement this PR brings is worth this possible annoyance for users of the Note that @stof refers to one third-party bundle that works without this interface by implementing the loading itself. (The failing test is for PHP 7 is completely unrelated.) |
I think we don't need this one: optimized caching is already dealt with on PHP7, where static arrays and static strings are far superior optimizing strategies. Thus, no need to do anything more on our side to me. |
@mpdude any thoughts on what Nicolas said? |
Closing as explained. Of course, please reopen if you don't agree. |
I opened this a while ago when I was working on a project where we had issues due to a large number of languages supported and comprehensive catalogs. We found other ways to work around this and I cannot tell whether the problem would still appear on PHP7. So, closing this is fine for me. Will reopen it or make a new case should I run into it again. |
We would like the
Translator
to be able to perform various optimizations on theMessageCatalogues
it holds internally. One particular example is working with reduced catalogues for fallback locales that only contain the messages not present in one of the more preferred locales, or possibly do a lazy-loading of catalogues for fallback locales.These optimizations are not possible as long as clients are able to retrieve the
MessageCatalogue
instances used inside theTranslator
by means of theTranslatorBagInterface
and expect them to be full-fledged and complete catalogue instances (so the initial attempt had to be reverted in #14315, also see #14380 for a discussion).In other words,
TranslatorBagInterface
breaks a boundary of encapsulation important for optimizations.The two clients of the interface inside Symfony are not really interested in the catalogues per se, but only need them to iterate along the fallback chain in order to figure out the locale ultimately used. This information can now be obtained through the new
FallbackLocaleAwareInterface
.To be discussed:
FallbackLocaleAwareInterface
remain a dedicated interface or become part ofTranslatorInterface
?TranslatorBagInterface
in the future, especially ifTranslator
does not implement it?