From core perspective, ParserOutput::setLanguageLinks() should accept an array of LinkTargets. What happens now is that Parser has a LinkTarget, formats it to prefixed text, then Skin/Api (basically all usages of it) parses it again into Title, or even worse implements its own custom parsing, like LinksUpdate.
Currently accepts an array of the form:
$languageLinks[$languageCode] = $languageCode . ':' . $siteLink->getPageName();
Should probably have an API like:
public function addLanguageLink(string $langCode, LinkTarget page);
Note that core does not seem to use ::setLanguageLinks() at all any more. Perhaps this entire method should be deprecated and removed instead?
The ::addLanguageLink() method, on the other hand, is significantly used. It should also take a LinkTarget argument.
Note also that includes/deferred/LinksUpdate/LangLinksTable.php in mediawiki-core also has its own ideas about the ParserOuput format for language links.