Translations were stored in a $GLOBALS array and handled by a static class Piwik\Translate. Furthermore, handling of translations were spread all over the place, caching logic was mixed with translation logic, …

This refactoring contains:

created a Translation component following the naming of Symfony's Translation component ("Translator" class, "Loaders", …)

all logic related to loading/handling translations is now encapsulated in that component

classes of that component are using dependency injection

Piwik\Translate is kept for BC and forwards call to the new Translator class

that new component is decoupled from the rest of Piwik (except for a few exceptions to improve later): it doesn't know about the HTTP request, about Plugins, about Piwik directories, etc...

translations are lazily loaded, i.e. you ask for a french translation then french translations will be loaded automatically

that means that Piwik/plugins don't have to tell the translator to load anything: the plugin manager just configures the directories where to find translations (which are the installed plugins…)

there is a LoaderInterface with the following implementations:

JsonFileLoader

LoaderCache: caches another loader by wrapping it (which would be the JsonFileLoader)

that way of caching things brings the following benefits:

caching can be configured in DI, and disabled with the container using the new dev environment (which addresses this TODO)

core translations are cached as well as the plugin ones, which fixes #6060

as said above, there's a new dev environment (= new DI config file) where translation cache is disabled: this environment can be used for other things as well

there is now a fallback mechanism (previously all translations were merged together in one array): if a french/… translation is not found, then the english one is returned

that fallback mechanism would allow to do #4983 (regional overrides) by having multiple fallbacks, for example: fr_CA (canadian french) would fallback to fr which would fallback to en (not implemented)

moved Piwik\Translate\Writer and its subclasses to the LanguagesManager plugin because these classes were only used in that plugin

And I was able to unit tests the new classes, which is just an awesome feeling :)

There's still a lot of room for improvement, I'll keep working on that PR. Feedback welcome!