Hi Niklas!
Do you see any downsides of using code like below instead?
'Translate:TranslatablePageParser' => function (): TranslatablePageParser { $services = TranslateServices::getInstance(); return new TranslatablePageParser( $services->getParsingPlaceholderFactory() ); },
The only downside is that it uses global state. In a future in which we'll some day have multiple instances of MediaWikiServices, one for the local wiki and one for each "sibling" wiki we want to access, this wouldn't work.
But then, this future is probably still pretty far off, and this would be easy to change. On the other hand, a typo in $services->get( 'Translate:ParsingPlaceholderFactory' ) is spotted quickly, and the lack of auto completion in the wiring file (and only in the wiring file) isn't so terrible, is it?
A cleaner solution would be for TranslateServices to not implement ContainerInterface directly, but extend ServiceContainer. That way, it would have its own wiring, instead of contribution to the wiring in MediaWikiServices. And the first parameter passed to instantiator callbacks would be the TranslateServices, not MediaWikiServices. If you also want MediaWikiServices to be passed in as well as the second parameter, you can supply it to the constructor of ServiceContainer via the $extraInstantiationParams parameter.
By the way, you can manage your singleton of TranslateServices as a static variable, but if you want to prepare for the bright an shiny future, you can also make TranslateServices a service in MediaWikiServices :)