-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Description
I would like to propose deprecating the concept of fallback catalogues, in particular the addFallbackCatalogue()
and getFallbackCatalogue()
methods, in MessageCatalogueInterface
and to remove the corresponding implementations from MessageCatalogue
in Symfony 3.0.
I will try to work out the details and come up with a PR once the basic idea gets approval.
Here's why.
Background
A MessageCatalogue
contains a set of translations (message id => translation string mappings) for a particular locale (e.g. de_DE
).
The concept of "fallback catalogues" is currently used to implement a "chain of responsibility" pattern across different MessageCatalogue
instances, each on holding translations for a different locale.
That way, you can query the "root" catalogue for the translation for a given message id (the get()
method) and the "best" translation is returned. This happens without exposing to the client which catalogue (locale) this translation was actually taken from. Internally, the call is forwarded to the respective fallback catalogue if a particular catalogue does not contain a message itself.
By means of the getFallbackCatalogue()
method, you could also explicitly navigate across catalogues (starting from the root). The has()
and defines()
methods can be used to check for messages in an entire catalogue chain or single catalogue, respectively.
Reasons for removal
1 - Complete transparency doesn't work for clients anyway
The Translator
class, which is the main MessageCatalogueInterface
client inside Symfony, has two main methods: trans()
and transChoice()
.
While trans()
can make use of transparent retrieval of messages, transChoice()
needs to be aware of a translation’s locale in order to apply pluralization rules correctly.
Thus, the transparent lookup across catalogues (with the current design) only works out in half of the primary use cases.
2 - Allow for optimizations inside Translator
Because the Translator
class allows to get the MessageCatalogue
instances used internally, clients were able to retrieve the primary and thus fallback catalogues from it.
Now, in Symfony 2.7 an attempt was made to optimize Translator
memory usage. Smaller fallback catalogues would be cached and contain only those messages for IDs not present in the "parent" catalogues.
At least in the available implementation, clients accessing the fallback catalogues would see different sets of messages depending on whether the Translator
had a warm cache or not. This is one of the reasons why this change was reverted for the time being.
If the fallback catalogues were not part of the MessageCatalogueInterface
, the Translator
could hold smaller MessageCatalogue
instances internally and query them in fallback order. But as long as clients can reach out for them (and expect "complete") fallback catalogues, that optimization is not possible.
3 - A consistent (and optimizable) API design would be difficult to achieve
An alternative approach to this optimization would be to make fallback catalogues always contain only those messages not present in one of the "parent" catalogues. Strictly speaking, this would still be a BC break (code behaves differently right now), but could even be argued to be in line with what the API docs suggest.
However I am afraid that such an API would be very cumbersome to use (depending on catalogues being nested/wired up in a particular order and/or not changing catalogues once the chain has been established) or a little mess internally (every catalogue knowing about its ancestor chain and virtually exposing messages only if not already present upstream).
Replacement
As mentioned under 2) above, clients could simply hold a list of catalogues to query successively instead of relying on the internal fallback mechanism.
If really needed, a ChainedMessageCatalogue
could possibly be provided to "decorate" the chain of responsibility pattern around individual catalogues.